Implemented dashboard and login/logout
497
v1/app.go
|
@ -7,17 +7,27 @@ import (
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/tylertravisty/rum-goggles/v1/internal/api"
|
||||||
"github.com/tylertravisty/rum-goggles/v1/internal/config"
|
"github.com/tylertravisty/rum-goggles/v1/internal/config"
|
||||||
"github.com/tylertravisty/rum-goggles/v1/internal/models"
|
"github.com/tylertravisty/rum-goggles/v1/internal/models"
|
||||||
rumblelivestreamlib "github.com/tylertravisty/rumble-livestream-lib-go"
|
rumblelivestreamlib "github.com/tylertravisty/rumble-livestream-lib-go"
|
||||||
|
"github.com/wailsapp/wails/v2/pkg/runtime"
|
||||||
|
|
||||||
_ "github.com/mattn/go-sqlite3"
|
_ "github.com/mattn/go-sqlite3"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
AccountType = "Account"
|
||||||
|
ChannelType = "Channel"
|
||||||
|
)
|
||||||
|
|
||||||
// App struct
|
// App struct
|
||||||
type App struct {
|
type App struct {
|
||||||
|
api *api.Api
|
||||||
clients map[string]*rumblelivestreamlib.Client
|
clients map[string]*rumblelivestreamlib.Client
|
||||||
|
clientsMu sync.Mutex
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
services *models.Services
|
services *models.Services
|
||||||
logError *log.Logger
|
logError *log.Logger
|
||||||
|
@ -36,6 +46,8 @@ func NewApp() *App {
|
||||||
log.Fatal("error initializing log: ", err)
|
log.Fatal("error initializing log: ", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
app.api = api.NewApi(app.logError, app.logInfo)
|
||||||
|
|
||||||
return app
|
return app
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,6 +70,7 @@ func (a *App) log() error {
|
||||||
// so we can call the runtime methods
|
// so we can call the runtime methods
|
||||||
func (a *App) startup(ctx context.Context) {
|
func (a *App) startup(ctx context.Context) {
|
||||||
a.ctx = ctx
|
a.ctx = ctx
|
||||||
|
a.api.Startup(ctx)
|
||||||
|
|
||||||
db, err := config.Database()
|
db, err := config.Database()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -85,6 +98,13 @@ func (a *App) startup(ctx context.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) shutdown(ctx context.Context) {
|
func (a *App) shutdown(ctx context.Context) {
|
||||||
|
if a.api != nil {
|
||||||
|
err := a.api.Shutdown()
|
||||||
|
if err != nil {
|
||||||
|
a.logError.Println("error shutting down api:", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if a.services != nil {
|
if a.services != nil {
|
||||||
err := a.services.Close()
|
err := a.services.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -102,7 +122,7 @@ func (a *App) shutdown(ctx context.Context) {
|
||||||
a.logFileMu.Unlock()
|
a.logFileMu.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) AddChannel(apiKey string) error {
|
func (a *App) AddPage(apiKey string) error {
|
||||||
client := rumblelivestreamlib.Client{StreamKey: apiKey}
|
client := rumblelivestreamlib.Client{StreamKey: apiKey}
|
||||||
resp, err := client.Request()
|
resp, err := client.Request()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -140,7 +160,7 @@ func (a *App) addAccountNotExist(uid string, username string, apiKey string) err
|
||||||
return fmt.Errorf("error querying account by username: %v", err)
|
return fmt.Errorf("error querying account by username: %v", err)
|
||||||
}
|
}
|
||||||
if acct == nil {
|
if acct == nil {
|
||||||
err = a.services.AccountS.Create(&models.Account{
|
_, err = a.services.AccountS.Create(&models.Account{
|
||||||
UID: &uid,
|
UID: &uid,
|
||||||
Username: &username,
|
Username: &username,
|
||||||
ApiKey: &apiKey,
|
ApiKey: &apiKey,
|
||||||
|
@ -182,6 +202,8 @@ func (a *App) addChannelNotExist(username string, cid string, name string, apiKe
|
||||||
|
|
||||||
func (a *App) Login(username string, password string) error {
|
func (a *App) Login(username string, password string) error {
|
||||||
var err error
|
var err error
|
||||||
|
a.clientsMu.Lock()
|
||||||
|
defer a.clientsMu.Unlock()
|
||||||
client, exists := a.clients[username]
|
client, exists := a.clients[username]
|
||||||
if exists && client != nil {
|
if exists && client != nil {
|
||||||
err = client.Logout()
|
err = client.Logout()
|
||||||
|
@ -207,27 +229,107 @@ func (a *App) Login(username string, password string) error {
|
||||||
}
|
}
|
||||||
cookiesS := string(cookiesB)
|
cookiesS := string(cookiesB)
|
||||||
|
|
||||||
act, err := a.services.AccountS.ByUsername(username)
|
acct, err := a.services.AccountS.ByUsername(username)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.logError.Println("error getting account by username:", err)
|
a.logError.Println("error getting account by username:", err)
|
||||||
return fmt.Errorf("Error logging in. Try again.")
|
return fmt.Errorf("Error logging in. Try again.")
|
||||||
}
|
}
|
||||||
if act == nil {
|
if acct == nil {
|
||||||
act = &models.Account{nil, nil, &username, &cookiesS, nil, nil}
|
acct = &models.Account{nil, nil, &username, &cookiesS, nil, nil}
|
||||||
err = a.services.AccountS.Create(act)
|
id, err := a.services.AccountS.Create(acct)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.logError.Println("error creating account:", err)
|
a.logError.Println("error creating account:", err)
|
||||||
return fmt.Errorf("Error logging in. Try again.")
|
return fmt.Errorf("Error logging in. Try again.")
|
||||||
}
|
}
|
||||||
|
acct.ID = &id
|
||||||
} else {
|
} else {
|
||||||
act.Cookies = &cookiesS
|
acct.Cookies = &cookiesS
|
||||||
err = a.services.AccountS.Update(act)
|
err = a.services.AccountS.Update(acct)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.logError.Println("error updating account:", err)
|
a.logError.Println("error updating account:", err)
|
||||||
return fmt.Errorf("Error logging in. Try again.")
|
return fmt.Errorf("Error logging in. Try again.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
name := acct.String()
|
||||||
|
if name == nil {
|
||||||
|
a.logError.Println("account name is nil")
|
||||||
|
return fmt.Errorf("Error logging in. Try again.")
|
||||||
|
}
|
||||||
|
runtime.EventsEmit(a.ctx, "LoggedIn-"+*name, true)
|
||||||
|
|
||||||
|
list, err := a.accountList()
|
||||||
|
if err != nil {
|
||||||
|
a.logError.Println("error getting account list:", err)
|
||||||
|
return fmt.Errorf("Error logging in. Try again.")
|
||||||
|
}
|
||||||
|
runtime.EventsEmit(a.ctx, "PageSideBarAccounts", list)
|
||||||
|
|
||||||
|
err = a.openDetails(acct)
|
||||||
|
if err != nil {
|
||||||
|
a.logError.Println("error opening account details:", err)
|
||||||
|
return fmt.Errorf("Error logging in. Try again.")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *App) Logout(id int64) error {
|
||||||
|
acct, err := a.services.AccountS.ByID(id)
|
||||||
|
if err != nil {
|
||||||
|
a.logError.Println("error querying account by ID:", err)
|
||||||
|
return fmt.Errorf("Error logging out. Try again.")
|
||||||
|
}
|
||||||
|
if acct == nil {
|
||||||
|
return fmt.Errorf("Did not find account. Try again.")
|
||||||
|
}
|
||||||
|
|
||||||
|
if acct.Username == nil {
|
||||||
|
a.logError.Println("account username is nil")
|
||||||
|
return fmt.Errorf("Error logging out. Try again.")
|
||||||
|
}
|
||||||
|
|
||||||
|
a.clientsMu.Lock()
|
||||||
|
defer a.clientsMu.Unlock()
|
||||||
|
client, exists := a.clients[*acct.Username]
|
||||||
|
if exists {
|
||||||
|
err = client.Logout()
|
||||||
|
if err != nil {
|
||||||
|
a.logError.Println("error logging out:", err)
|
||||||
|
return fmt.Errorf("Error logging out. Try again.")
|
||||||
|
}
|
||||||
|
delete(a.clients, *acct.Username)
|
||||||
|
}
|
||||||
|
|
||||||
|
if acct.Cookies != nil {
|
||||||
|
acct.Cookies = nil
|
||||||
|
err = a.services.AccountS.Update(acct)
|
||||||
|
if err != nil {
|
||||||
|
a.logError.Println("error updating account:", err)
|
||||||
|
return fmt.Errorf("Error logging out. Try again.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
name := acct.String()
|
||||||
|
if name == nil {
|
||||||
|
a.logError.Println("account name is nil")
|
||||||
|
return fmt.Errorf("Error logging out. Try again.")
|
||||||
|
}
|
||||||
|
runtime.EventsEmit(a.ctx, "LoggedIn-"+*name, false)
|
||||||
|
|
||||||
|
list, err := a.accountList()
|
||||||
|
if err != nil {
|
||||||
|
a.logError.Println("error getting account list:", err)
|
||||||
|
return fmt.Errorf("Error logging out. Try again.")
|
||||||
|
}
|
||||||
|
runtime.EventsEmit(a.ctx, "PageSideBarAccounts", list)
|
||||||
|
|
||||||
|
err = a.openDetails(acct)
|
||||||
|
if err != nil {
|
||||||
|
a.logError.Println("error opening account details:", err)
|
||||||
|
return fmt.Errorf("Error logging out. Try again.")
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -247,18 +349,26 @@ type Account struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) AccountList() (map[string]*Account, error) {
|
func (a *App) AccountList() (map[string]*Account, error) {
|
||||||
|
list, err := a.accountList()
|
||||||
|
if err != nil {
|
||||||
|
a.logError.Println("error getting account list:", err)
|
||||||
|
return nil, fmt.Errorf("Error retrieving accounts and channels. Try restarting.")
|
||||||
|
}
|
||||||
|
|
||||||
|
return list, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *App) accountList() (map[string]*Account, error) {
|
||||||
list := map[string]*Account{}
|
list := map[string]*Account{}
|
||||||
|
|
||||||
accountChannels, err := a.services.AccountChannelS.All()
|
accountChannels, err := a.services.AccountChannelS.All()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.logError.Println("error getting all account channels:", err)
|
return nil, fmt.Errorf("error querying all account channels: %v", err)
|
||||||
return nil, fmt.Errorf("Error retrieving accounts and channels. Try restarting.")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, ac := range accountChannels {
|
for _, ac := range accountChannels {
|
||||||
if ac.Account.Username == nil {
|
if ac.Account.Username == nil {
|
||||||
a.logError.Println("account-channel contains nil account username")
|
return nil, fmt.Errorf("account-channel contains nil account username")
|
||||||
return nil, fmt.Errorf("Error retrieving accounts and channels. Try restarting.")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
act, exists := list[*ac.Account.Username]
|
act, exists := list[*ac.Account.Username]
|
||||||
|
@ -274,3 +384,366 @@ func (a *App) AccountList() (map[string]*Account, error) {
|
||||||
|
|
||||||
return list, nil
|
return list, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *App) OpenAccount(id int64) error {
|
||||||
|
acct, err := a.services.AccountS.ByID(id)
|
||||||
|
if err != nil {
|
||||||
|
a.logError.Println("error querying account by ID:", err)
|
||||||
|
return fmt.Errorf("Error opening account. Try again.")
|
||||||
|
}
|
||||||
|
if acct == nil {
|
||||||
|
return fmt.Errorf("Did not find account. Try again.")
|
||||||
|
}
|
||||||
|
|
||||||
|
err = a.openDetails(acct)
|
||||||
|
if err != nil {
|
||||||
|
a.logError.Println("error opening account details:", err)
|
||||||
|
return fmt.Errorf("Error opening account. Try again.")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *App) OpenChannel(id int64) error {
|
||||||
|
channel, err := a.services.ChannelS.ByID(id)
|
||||||
|
if err != nil {
|
||||||
|
a.logError.Println("error querying channel by ID:", err)
|
||||||
|
return fmt.Errorf("Error opening channel. Try again.")
|
||||||
|
}
|
||||||
|
if channel == nil {
|
||||||
|
return fmt.Errorf("Did not find channel. Try again.")
|
||||||
|
}
|
||||||
|
|
||||||
|
err = a.openDetails(channel)
|
||||||
|
if err != nil {
|
||||||
|
a.logError.Println("error opening channel details:", err)
|
||||||
|
return fmt.Errorf("Error opening channel. Try again.")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type Page interface {
|
||||||
|
Id() *int64
|
||||||
|
KeyUrl() *string
|
||||||
|
LoggedIn() bool
|
||||||
|
String() *string
|
||||||
|
Title() *string
|
||||||
|
Type() string
|
||||||
|
}
|
||||||
|
|
||||||
|
type PageDetails struct {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
HasApi bool `json:"has_api"`
|
||||||
|
LoggedIn bool `json:"logged_in"`
|
||||||
|
Title string `json:"title"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *App) openDetails(p Page) error {
|
||||||
|
id := p.Id()
|
||||||
|
if id == nil {
|
||||||
|
return fmt.Errorf("page id is nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
hasApi := true
|
||||||
|
key := p.KeyUrl()
|
||||||
|
if key == nil || *key == "" {
|
||||||
|
hasApi = false
|
||||||
|
}
|
||||||
|
|
||||||
|
name := p.String()
|
||||||
|
if name == nil {
|
||||||
|
return fmt.Errorf("page name is nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
title := p.Title()
|
||||||
|
if title == nil {
|
||||||
|
return fmt.Errorf("page title is nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
runtime.EventsEmit(a.ctx, "PageDetails", PageDetails{
|
||||||
|
ID: *id,
|
||||||
|
HasApi: hasApi,
|
||||||
|
LoggedIn: p.LoggedIn(),
|
||||||
|
Title: *title,
|
||||||
|
Type: p.Type(),
|
||||||
|
})
|
||||||
|
|
||||||
|
err := a.api.Display(*name)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error displaying api for %s: %v", *name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *App) ActivateAccount(id int64) error {
|
||||||
|
acct, err := a.services.AccountS.ByID(id)
|
||||||
|
if err != nil {
|
||||||
|
a.logError.Println("error querying account by ID:", err)
|
||||||
|
return fmt.Errorf("Error activating account. Try again.")
|
||||||
|
}
|
||||||
|
if acct == nil {
|
||||||
|
return fmt.Errorf("Did not find account. Try again.")
|
||||||
|
}
|
||||||
|
|
||||||
|
err = a.activatePage(acct)
|
||||||
|
if err != nil {
|
||||||
|
a.logError.Println("error activating account:", err)
|
||||||
|
return fmt.Errorf("Error activating account. Try again.")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ActivateChannel activates an inactivate page and deactivates an active page.
|
||||||
|
func (a *App) ActivateChannel(id int64) error {
|
||||||
|
channel, err := a.services.ChannelS.ByID(id)
|
||||||
|
if err != nil {
|
||||||
|
a.logError.Println("error querying channel by ID:", err)
|
||||||
|
return fmt.Errorf("Error activating channel. Try again.")
|
||||||
|
}
|
||||||
|
if channel == nil {
|
||||||
|
return fmt.Errorf("Did not find channel. Try again.")
|
||||||
|
}
|
||||||
|
|
||||||
|
err = a.activatePage(channel)
|
||||||
|
if err != nil {
|
||||||
|
a.logError.Println("error activating channel:", err)
|
||||||
|
return fmt.Errorf("Error activating channel. Try again.")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// If page is inactivate, activate.
|
||||||
|
// If page is active, deactivate.
|
||||||
|
func (a *App) activatePage(p Page) error {
|
||||||
|
name := p.String()
|
||||||
|
if name == nil {
|
||||||
|
return fmt.Errorf("page name is nil")
|
||||||
|
}
|
||||||
|
url := p.KeyUrl()
|
||||||
|
if url == nil {
|
||||||
|
return fmt.Errorf("page key url is nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
if a.api.Active(*name) {
|
||||||
|
err := a.api.Stop(*name)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error stopping api: %v", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
err := a.api.Start(*name, *url, 10*time.Second)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error starting api: %v", err)
|
||||||
|
}
|
||||||
|
err = a.api.Display(*name)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error displaying api: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *App) DeleteAccount(id int64) error {
|
||||||
|
acct, err := a.services.AccountS.ByID(id)
|
||||||
|
if err != nil {
|
||||||
|
a.logError.Println("error querying account by ID:", err)
|
||||||
|
return fmt.Errorf("Error deleting account. Try again.")
|
||||||
|
}
|
||||||
|
if acct == nil {
|
||||||
|
return fmt.Errorf("Did not find account. Try again.")
|
||||||
|
}
|
||||||
|
|
||||||
|
channels, err := a.services.ChannelS.ByAccount(acct)
|
||||||
|
if err != nil {
|
||||||
|
a.logError.Println("error querying channels by account:", err)
|
||||||
|
return fmt.Errorf("Error deleting account. Try again.")
|
||||||
|
}
|
||||||
|
if len(channels) != 0 {
|
||||||
|
return fmt.Errorf("You must delete all channels associated with the account before it can be deleted.")
|
||||||
|
}
|
||||||
|
|
||||||
|
name := acct.String()
|
||||||
|
if name == nil {
|
||||||
|
a.logError.Println("account name is nil")
|
||||||
|
return fmt.Errorf("Error deleting account. Try again.")
|
||||||
|
}
|
||||||
|
|
||||||
|
if a.api.Active(*name) {
|
||||||
|
err := a.api.Stop(*name)
|
||||||
|
if err != nil {
|
||||||
|
a.logError.Println("error stopping api:", err)
|
||||||
|
return fmt.Errorf("Error deleting account. Try again.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err = a.services.AccountS.Delete(acct)
|
||||||
|
if err != nil {
|
||||||
|
a.logError.Println("error deleting account:", err)
|
||||||
|
return fmt.Errorf("Error deleting account. Try again.")
|
||||||
|
}
|
||||||
|
|
||||||
|
runtime.EventsEmit(a.ctx, "PageDetails", nil)
|
||||||
|
|
||||||
|
list, err := a.accountList()
|
||||||
|
if err != nil {
|
||||||
|
a.logError.Println("error getting account list:", err)
|
||||||
|
return fmt.Errorf("Error deleting account. Try again.")
|
||||||
|
}
|
||||||
|
|
||||||
|
runtime.EventsEmit(a.ctx, "PageSideBarAccounts", list)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *App) DeleteChannel(id int64) error {
|
||||||
|
channel, err := a.services.ChannelS.ByID(id)
|
||||||
|
if err != nil {
|
||||||
|
a.logError.Println("error querying channel by ID:", err)
|
||||||
|
return fmt.Errorf("Error deleting channel. Try again.")
|
||||||
|
}
|
||||||
|
if channel == nil {
|
||||||
|
return fmt.Errorf("Did not find channel. Try again.")
|
||||||
|
}
|
||||||
|
|
||||||
|
name := channel.String()
|
||||||
|
if name == nil {
|
||||||
|
a.logError.Println("channel name is nil")
|
||||||
|
return fmt.Errorf("Error deleting channel. Try again.")
|
||||||
|
}
|
||||||
|
|
||||||
|
if a.api.Active(*name) {
|
||||||
|
err := a.api.Stop(*name)
|
||||||
|
if err != nil {
|
||||||
|
a.logError.Println("error stopping api:", err)
|
||||||
|
return fmt.Errorf("Error deleting channel. Try again.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err = a.services.ChannelS.Delete(channel)
|
||||||
|
if err != nil {
|
||||||
|
a.logError.Println("error deleting channel:", err)
|
||||||
|
return fmt.Errorf("Error deleting channel. Try again.")
|
||||||
|
}
|
||||||
|
|
||||||
|
runtime.EventsEmit(a.ctx, "PageDetails", nil)
|
||||||
|
|
||||||
|
list, err := a.accountList()
|
||||||
|
if err != nil {
|
||||||
|
a.logError.Println("error getting account list:", err)
|
||||||
|
return fmt.Errorf("Error deleting channel. Try again.")
|
||||||
|
}
|
||||||
|
|
||||||
|
runtime.EventsEmit(a.ctx, "PageSideBarAccounts", list)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *App) PageStatus(name string) {
|
||||||
|
active := false
|
||||||
|
isLive := false
|
||||||
|
|
||||||
|
resp := a.api.Response(name)
|
||||||
|
if resp != nil {
|
||||||
|
active = true
|
||||||
|
isLive = len(resp.Livestreams) > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
runtime.EventsEmit(a.ctx, "ApiActive-"+name, active)
|
||||||
|
runtime.EventsEmit(a.ctx, "PageLive-"+name, isLive)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *App) UpdateAccountApi(id int64, apiKey string) error {
|
||||||
|
acct, err := a.services.AccountS.ByID(id)
|
||||||
|
if err != nil {
|
||||||
|
a.logError.Println("error querying account by ID:", err)
|
||||||
|
return fmt.Errorf("Error updating account. Try again.")
|
||||||
|
}
|
||||||
|
if acct == nil {
|
||||||
|
return fmt.Errorf("Did not find account. Try again.")
|
||||||
|
}
|
||||||
|
|
||||||
|
name := acct.String()
|
||||||
|
if name == nil {
|
||||||
|
a.logError.Println("account name is nil")
|
||||||
|
return fmt.Errorf("Error updating account. Try again.")
|
||||||
|
}
|
||||||
|
|
||||||
|
if a.api.Active(*name) {
|
||||||
|
err := a.api.Stop(*name)
|
||||||
|
if err != nil {
|
||||||
|
a.logError.Println("error stopping api:", err)
|
||||||
|
return fmt.Errorf("Error updating account. Try again.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
client := rumblelivestreamlib.Client{StreamKey: apiKey}
|
||||||
|
resp, err := client.Request()
|
||||||
|
if err != nil {
|
||||||
|
a.logError.Println("error executing api request:", err)
|
||||||
|
return fmt.Errorf("Error querying API. Verify key and try again.")
|
||||||
|
}
|
||||||
|
|
||||||
|
if resp.ChannelName != "" || resp.Username != *acct.Username {
|
||||||
|
return fmt.Errorf("API key does not belong to account. Verify key and try again.")
|
||||||
|
}
|
||||||
|
|
||||||
|
acct.ApiKey = &apiKey
|
||||||
|
err = a.services.AccountS.Update(acct)
|
||||||
|
if err != nil {
|
||||||
|
a.logError.Println("error updating account:", err)
|
||||||
|
return fmt.Errorf("Error updating account. Try again.")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *App) UpdateChannelApi(id int64, apiKey string) error {
|
||||||
|
channel, err := a.services.ChannelS.ByID(id)
|
||||||
|
if err != nil {
|
||||||
|
a.logError.Println("error querying channel by ID:", err)
|
||||||
|
return fmt.Errorf("Error updating channel. Try again.")
|
||||||
|
}
|
||||||
|
if channel == nil {
|
||||||
|
return fmt.Errorf("Did not find channel. Try again.")
|
||||||
|
}
|
||||||
|
|
||||||
|
name := channel.String()
|
||||||
|
if name == nil {
|
||||||
|
a.logError.Println("channel name is nil")
|
||||||
|
return fmt.Errorf("Error updating channel. Try again.")
|
||||||
|
}
|
||||||
|
|
||||||
|
if a.api.Active(*name) {
|
||||||
|
err := a.api.Stop(*name)
|
||||||
|
if err != nil {
|
||||||
|
a.logError.Println("error stopping api:", err)
|
||||||
|
return fmt.Errorf("Error updating channel. Try again.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
client := rumblelivestreamlib.Client{StreamKey: apiKey}
|
||||||
|
resp, err := client.Request()
|
||||||
|
if err != nil {
|
||||||
|
a.logError.Println("error executing api request:", err)
|
||||||
|
return fmt.Errorf("Error querying API. Verify key and try again.")
|
||||||
|
}
|
||||||
|
|
||||||
|
if resp.ChannelName != *channel.Name {
|
||||||
|
return fmt.Errorf("API key does not belong to channel. Verify key and try again.")
|
||||||
|
}
|
||||||
|
|
||||||
|
*channel.ApiKey = apiKey
|
||||||
|
err = a.services.ChannelS.Update(channel)
|
||||||
|
if err != nil {
|
||||||
|
a.logError.Println("error updating channel:", err)
|
||||||
|
return fmt.Errorf("Error updating channel. Try again.")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
BIN
v1/frontend/src/assets/icons/eye-red.png
Normal file
After Width: | Height: | Size: 6.6 KiB |
BIN
v1/frontend/src/assets/icons/gear-fill.png
Normal file
After Width: | Height: | Size: 6 KiB |
BIN
v1/frontend/src/assets/icons/hand-thumbs-down-fill.png
Normal file
After Width: | Height: | Size: 3.6 KiB |
BIN
v1/frontend/src/assets/icons/hand-thumbs-up-fill.png
Normal file
After Width: | Height: | Size: 3.5 KiB |
BIN
v1/frontend/src/assets/icons/pause-circle-green.png
Normal file
After Width: | Height: | Size: 7.2 KiB |
BIN
v1/frontend/src/assets/icons/pause-circle.png
Normal file
After Width: | Height: | Size: 5.3 KiB |
BIN
v1/frontend/src/assets/icons/pause-fill.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
v1/frontend/src/assets/icons/play-circle-green.png
Normal file
After Width: | Height: | Size: 7.1 KiB |
BIN
v1/frontend/src/assets/icons/play-circle.png
Normal file
After Width: | Height: | Size: 5.3 KiB |
BIN
v1/frontend/src/assets/icons/play-fill.png
Normal file
After Width: | Height: | Size: 2.3 KiB |
BIN
v1/frontend/src/assets/icons/star-fill.png
Normal file
After Width: | Height: | Size: 4.8 KiB |
|
@ -1,17 +1,33 @@
|
||||||
import chevron_right from './icons/chevron-right.png';
|
import chevron_right from './icons/chevron-right.png';
|
||||||
import circle_green_background from './icons/circle-green-background.png';
|
import circle_green_background from './icons/circle-green-background.png';
|
||||||
|
import circle_red_background from './icons/circle-red-background.png';
|
||||||
import eye from './icons/eye.png';
|
import eye from './icons/eye.png';
|
||||||
|
import eye_red from './icons/eye-red.png';
|
||||||
import eye_slash from './icons/eye-slash.png';
|
import eye_slash from './icons/eye-slash.png';
|
||||||
|
import gear_fill from './icons/gear-fill.png';
|
||||||
import heart from './icons/heart-fill.png';
|
import heart from './icons/heart-fill.png';
|
||||||
import plus_circle from './icons/plus-circle-fill.png'
|
import pause from './icons/pause-circle-green.png';
|
||||||
|
import play from './icons/play-circle-green.png';
|
||||||
|
import plus_circle from './icons/plus-circle-fill.png';
|
||||||
|
import star from './icons/star-fill.png';
|
||||||
|
import thumbs_down from './icons/hand-thumbs-down-fill.png';
|
||||||
|
import thumbs_up from './icons/hand-thumbs-up-fill.png';
|
||||||
import x_lg from './icons/x-lg.png';
|
import x_lg from './icons/x-lg.png';
|
||||||
import logo from './logo/logo.png';
|
import logo from './logo/logo.png';
|
||||||
|
|
||||||
export const ChevronRight = chevron_right;
|
export const ChevronRight = chevron_right;
|
||||||
export const CircleGreenBackground = circle_green_background;
|
export const CircleGreenBackground = circle_green_background;
|
||||||
|
export const CircleRedBackground = circle_red_background;
|
||||||
export const Eye = eye;
|
export const Eye = eye;
|
||||||
|
export const EyeRed = eye_red;
|
||||||
export const EyeSlash = eye_slash;
|
export const EyeSlash = eye_slash;
|
||||||
|
export const Gear = gear_fill;
|
||||||
export const Heart = heart;
|
export const Heart = heart;
|
||||||
export const Logo = logo;
|
export const Logo = logo;
|
||||||
|
export const Pause = pause;
|
||||||
|
export const Play = play;
|
||||||
export const PlusCircle = plus_circle;
|
export const PlusCircle = plus_circle;
|
||||||
|
export const Star = star;
|
||||||
|
export const ThumbsDown = thumbs_down;
|
||||||
|
export const ThumbsUp = thumbs_up;
|
||||||
export const XLg = x_lg;
|
export const XLg = x_lg;
|
|
@ -31,7 +31,7 @@
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
/* width: 20%; */
|
/* width: 20%; */
|
||||||
height: 40px;
|
height: 40px;
|
||||||
width: 70px;
|
min-width: 70px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-button-cancel {
|
.modal-button-cancel {
|
||||||
|
@ -46,21 +46,35 @@
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
/* width: 20%; */
|
/* width: 20%; */
|
||||||
height: 40px;
|
height: 40px;
|
||||||
width: 70px;
|
min-width: 70px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-button-delete {
|
.modal-button-delete {
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
border: 1px solid red;
|
background-color: #f23160;
|
||||||
|
border: 1px solid #f23160;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
color: red;
|
color: #eee;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
/* width: 20%; */
|
|
||||||
height: 40px;
|
height: 40px;
|
||||||
width: 70px;
|
min-width: 70px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-button-delete-inactive {
|
||||||
|
background-color: transparent;
|
||||||
|
background-color: #d6e0ea80;
|
||||||
|
border: 1px solid #d6e0ea80;
|
||||||
|
border-radius: 5px;
|
||||||
|
color: #eee;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: bold;
|
||||||
|
text-decoration: none;
|
||||||
|
height: 40px;
|
||||||
|
min-width: 70px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-close {
|
.modal-close {
|
||||||
|
@ -121,6 +135,20 @@
|
||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.small-modal-button-cancel {
|
||||||
|
background-color: transparent;
|
||||||
|
border: 1px solid #495a6a;
|
||||||
|
border-radius: 5px;
|
||||||
|
color: #495a6a;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: bold;
|
||||||
|
text-decoration: none;
|
||||||
|
/* width: 20%; */
|
||||||
|
height: 40px;
|
||||||
|
min-width: 70px;
|
||||||
|
}
|
||||||
|
|
||||||
.small-modal-button-delete {
|
.small-modal-button-delete {
|
||||||
background-color: red;
|
background-color: red;
|
||||||
border: none;
|
border: none;
|
||||||
|
@ -131,7 +159,7 @@
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
/* width: 20%; */
|
/* width: 20%; */
|
||||||
width: 70px;
|
min-width: 70px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.small-modal-container {
|
.small-modal-container {
|
||||||
|
|
|
@ -27,7 +27,14 @@ export function Modal(props) {
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
{props.deleteButton && (
|
{props.deleteButton && (
|
||||||
<button className='modal-button-delete' onClick={props.onDelete}>
|
<button
|
||||||
|
className={
|
||||||
|
props.deleteActive
|
||||||
|
? 'modal-button-delete'
|
||||||
|
: 'modal-button-delete-inactive'
|
||||||
|
}
|
||||||
|
onClick={props.onDelete}
|
||||||
|
>
|
||||||
{props.deleteButton}
|
{props.deleteButton}
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
|
@ -70,7 +77,7 @@ export function SmallModal(props) {
|
||||||
</div>
|
</div>
|
||||||
<div className='small-modal-footer'>
|
<div className='small-modal-footer'>
|
||||||
{props.cancelButton && (
|
{props.cancelButton && (
|
||||||
<button className='modal-button-cancel' onClick={props.onCancel}>
|
<button className='small-modal-button-cancel' onClick={props.onCancel}>
|
||||||
{props.cancelButton}
|
{props.cancelButton}
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
|
|
356
v1/frontend/src/components/PageDetails.css
Normal file
|
@ -0,0 +1,356 @@
|
||||||
|
.modal-delete-page {
|
||||||
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100%;
|
||||||
|
justify-content: space-evenly;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-delete-page-header {
|
||||||
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-delete-page-input {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-delete-page-input-text {
|
||||||
|
background-color: #061726;
|
||||||
|
border: none;
|
||||||
|
border-radius: 5px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
color: white;
|
||||||
|
font-family: monospace;
|
||||||
|
font-size: 16px;
|
||||||
|
outline: none;
|
||||||
|
padding: 10px;
|
||||||
|
resize: none;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-delete-page-subtitle {
|
||||||
|
color: white;
|
||||||
|
font-family: sans-serif;
|
||||||
|
font-size: 14px;
|
||||||
|
margin-top: 10px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-delete-page-title {
|
||||||
|
color: white;
|
||||||
|
font-family: sans-serif;
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: bold;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-delete-page-body {
|
||||||
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-activity {
|
||||||
|
height: 100%;
|
||||||
|
overflow-y: auto;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-activity-header {
|
||||||
|
align-items: center;
|
||||||
|
border-bottom: 1px solid #061726;
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-evenly;
|
||||||
|
padding: 10px 20px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-activity-stat {
|
||||||
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-between;
|
||||||
|
width: 175px;
|
||||||
|
}
|
||||||
|
.page-activity-stat-text {
|
||||||
|
color: white;
|
||||||
|
font-family: monospace;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-activity-stat-title {
|
||||||
|
color: white;
|
||||||
|
font-family: sans-serif;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-details {
|
||||||
|
align-items: center;
|
||||||
|
background-color: #1f2e3c;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
height: 100%;
|
||||||
|
/* padding: 0px 10px; */
|
||||||
|
width: 300px;
|
||||||
|
min-width: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-details-footer {
|
||||||
|
align-items: start;
|
||||||
|
border-top: 1px solid #061726;
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
/* height: 50px; */
|
||||||
|
justify-content: center;
|
||||||
|
padding: 10px 0px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-details-footer-title {
|
||||||
|
color: #eee;
|
||||||
|
font-family: sans-serif;
|
||||||
|
font-weight: bold;
|
||||||
|
padding: 0px 10px 10px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-details-footer-categories {
|
||||||
|
align-items: center;
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: start;
|
||||||
|
padding: 0px 10px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-details-footer-category {
|
||||||
|
align-items: center;
|
||||||
|
box-sizing: border-box;
|
||||||
|
color: #eee;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
font-family: sans-serif;
|
||||||
|
font-weight: bold;
|
||||||
|
justify-content: center;
|
||||||
|
padding-bottom: 5px;
|
||||||
|
text-align: center;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-details-footer-stats {
|
||||||
|
align-items: center;
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-evenly;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-details-footer-stat {
|
||||||
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
|
width: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-details-footer-stat-icon {
|
||||||
|
height: 20px;
|
||||||
|
width: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-details-footer-stat-text {
|
||||||
|
color: white;
|
||||||
|
font-family: monospace;
|
||||||
|
font-size: 16px;
|
||||||
|
padding-left: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-details-footer-stat-text-red {
|
||||||
|
color: #f23160;
|
||||||
|
font-family: monospace;
|
||||||
|
font-size: 16px;
|
||||||
|
padding-left: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-details-header {
|
||||||
|
align-items: center;
|
||||||
|
border-bottom: 1px solid #061726;
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
/* min-height: 80px; */
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 10px 20px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-details-header-left {
|
||||||
|
align-items: start;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-details-header-right {
|
||||||
|
align-items: end;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-details-header-button {
|
||||||
|
align-items: center;
|
||||||
|
background-color: #1f2e3c;
|
||||||
|
border: none;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
padding-left: 10px;
|
||||||
|
padding-right: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-details-header-button:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-details-header-icon {
|
||||||
|
height: 24px;
|
||||||
|
width: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-details-header-title {
|
||||||
|
color: #eee;
|
||||||
|
font-family: sans-serif;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-details-header-type {
|
||||||
|
color: #eee;
|
||||||
|
font-family: sans-serif;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-details-settings {
|
||||||
|
background-color: #000312;
|
||||||
|
border-radius: 3px;
|
||||||
|
padding: 5px;
|
||||||
|
position: fixed;
|
||||||
|
transform: translate(0px, 60px);
|
||||||
|
transition: all 1s;
|
||||||
|
width: 270px;
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-details-settings-background {
|
||||||
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
|
height: 100vh;
|
||||||
|
justify-content: center;
|
||||||
|
left: 0;
|
||||||
|
opacity: 0;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
width: 100vw;
|
||||||
|
z-index: 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-details-settings-button {
|
||||||
|
color: #eee;
|
||||||
|
font-family: sans-serif;
|
||||||
|
font-size: 16px;
|
||||||
|
background-color: #000312;
|
||||||
|
border: none;
|
||||||
|
border-radius: 3px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 5px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.page-details-settings-button:hover {
|
||||||
|
background-color: #77b23b;
|
||||||
|
color: #000312;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-details-settings-text {
|
||||||
|
color: #eee;
|
||||||
|
font-family: sans-serif;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-event {
|
||||||
|
border-bottom: 1px solid #061726;
|
||||||
|
color: white;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
font-family: sans-serif;
|
||||||
|
justify-content: space-between;
|
||||||
|
overflow-x: wrap;
|
||||||
|
padding: 10px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-event-left {
|
||||||
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-event-icon {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
padding-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-event-left-text {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-event-username {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: bold;
|
||||||
|
max-width: 150px;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-event-description {
|
||||||
|
color: #88a0b8;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-event-date {
|
||||||
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
|
font-family: monospace;
|
||||||
|
text-align: end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-inactive {
|
||||||
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-inactive-text {
|
||||||
|
/* border: 1px solid #eee;
|
||||||
|
border-radius: 30px; */
|
||||||
|
color: #eee;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
795
v1/frontend/src/components/PageDetails.jsx
Normal file
|
@ -0,0 +1,795 @@
|
||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
import { EventsOn } from '../../wailsjs/runtime/runtime';
|
||||||
|
import {
|
||||||
|
Eye,
|
||||||
|
EyeRed,
|
||||||
|
EyeSlash,
|
||||||
|
Gear,
|
||||||
|
Heart,
|
||||||
|
Play,
|
||||||
|
Pause,
|
||||||
|
Star,
|
||||||
|
ThumbsDown,
|
||||||
|
ThumbsUp,
|
||||||
|
} from '../assets';
|
||||||
|
import './PageDetails.css';
|
||||||
|
import {
|
||||||
|
ActivateAccount,
|
||||||
|
ActivateChannel,
|
||||||
|
DeleteAccount,
|
||||||
|
DeleteChannel,
|
||||||
|
Login,
|
||||||
|
Logout,
|
||||||
|
UpdateAccountApi,
|
||||||
|
UpdateChannelApi,
|
||||||
|
} from '../../wailsjs/go/main/App';
|
||||||
|
import { Modal, SmallModal } from './Modal';
|
||||||
|
|
||||||
|
function countString(value) {
|
||||||
|
switch (true) {
|
||||||
|
case value <= 0 || value == undefined:
|
||||||
|
return '0';
|
||||||
|
case value < 1000:
|
||||||
|
return value;
|
||||||
|
case value < 1000000:
|
||||||
|
return (value / 1000).toFixed(3).slice(0, -2) + 'K';
|
||||||
|
case value < 1000000000:
|
||||||
|
return (value / 1000000).toFixed(6).slice(0, -5) + 'M';
|
||||||
|
default:
|
||||||
|
return 'Inf';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function PageDetails(props) {
|
||||||
|
const [activate, setActivate] = useState(false);
|
||||||
|
const [active, setActive] = useState(false);
|
||||||
|
const [activity, setActivity] = useState(null);
|
||||||
|
const [openApi, setOpenApi] = useState(false);
|
||||||
|
const [apiValid, setApiValid] = useState(true);
|
||||||
|
const [editingApi, setEditingApi] = useState(false);
|
||||||
|
const [editApi, setEditApi] = useState('');
|
||||||
|
const updateEditApi = (event) => {
|
||||||
|
setEditApi(event.target.value);
|
||||||
|
};
|
||||||
|
const [openDelete, setOpenDelete] = useState(false);
|
||||||
|
const [deleting, setDeleting] = useState(false);
|
||||||
|
const [deleteName, setDeleteName] = useState('');
|
||||||
|
const updateDeleteName = (event) => {
|
||||||
|
if (deleting) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setDeleteName(event.target.value);
|
||||||
|
};
|
||||||
|
const [details, setDetails] = useState(null);
|
||||||
|
const [error, setError] = useState('');
|
||||||
|
const [live, setLive] = useState(false);
|
||||||
|
const [liveTitle, setLiveTitle] = useState('');
|
||||||
|
const [openLogin, setOpenLogin] = useState(false);
|
||||||
|
const [loggingIn, setLoggingIn] = useState(false);
|
||||||
|
const [loginUsername, setLoginUsername] = useState('');
|
||||||
|
const updateLoginUsername = (event) => {
|
||||||
|
if (loggingIn) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setLoginUsername(event.target.value);
|
||||||
|
};
|
||||||
|
const [loginUsernameValid, setLoginUsernameValid] = useState(true);
|
||||||
|
const [loginPassword, setLoginPassword] = useState('');
|
||||||
|
const updateLoginPassword = (event) => {
|
||||||
|
if (loggingIn) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setLoginPassword(event.target.value);
|
||||||
|
};
|
||||||
|
const [loginPasswordValid, setLoginPasswordValid] = useState(true);
|
||||||
|
const [openLogout, setOpenLogout] = useState(false);
|
||||||
|
const [loggingOut, setLoggingOut] = useState(false);
|
||||||
|
const [settings, setSettings] = useState(false);
|
||||||
|
const triggerSettings = () => setSettings(!settings);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
EventsOn('PageDetails', (event) => {
|
||||||
|
setDetails(event);
|
||||||
|
// TODO: do I need to reset all editing/logging out/etc. values?
|
||||||
|
});
|
||||||
|
|
||||||
|
EventsOn('PageActivity', (event) => {
|
||||||
|
setActivity(event);
|
||||||
|
setActive(true);
|
||||||
|
if (event.livestreams.length > 0) {
|
||||||
|
setLive(true);
|
||||||
|
} else {
|
||||||
|
setLive(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
EventsOn('PageActive', (event) => {
|
||||||
|
if (event) {
|
||||||
|
setActive(true);
|
||||||
|
} else {
|
||||||
|
setActive(false);
|
||||||
|
setActivity(null);
|
||||||
|
setLive(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (deleting) {
|
||||||
|
switch (true) {
|
||||||
|
case details.type === 'Channel':
|
||||||
|
DeleteChannel(details.id)
|
||||||
|
.then(() => resetDelete())
|
||||||
|
.catch((error) => {
|
||||||
|
setDeleting(false);
|
||||||
|
setError(error);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
case details.type === 'Account':
|
||||||
|
DeleteAccount(details.id)
|
||||||
|
.then(() => resetDelete())
|
||||||
|
.catch((error) => {
|
||||||
|
setDeleting(false);
|
||||||
|
setError(error);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [deleting]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (editingApi) {
|
||||||
|
switch (true) {
|
||||||
|
case details.type === 'Channel':
|
||||||
|
UpdateChannelApi(details.id, editApi)
|
||||||
|
.then(() => resetEditApi())
|
||||||
|
.catch((error) => {
|
||||||
|
setEditingApi(false);
|
||||||
|
setError(error);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
case details.type === 'Account':
|
||||||
|
UpdateAccountApi(details.id, editApi)
|
||||||
|
.then(() => resetEditApi())
|
||||||
|
.catch((error) => {
|
||||||
|
setEditingApi(false);
|
||||||
|
setError(error);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [editingApi]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (loggingIn && details.type === 'Account') {
|
||||||
|
Login(loginUsername, loginPassword)
|
||||||
|
.then(() => {
|
||||||
|
resetLogin();
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
setLoggingIn(false);
|
||||||
|
setError(error);
|
||||||
|
});
|
||||||
|
} else if (loggingIn && details.type === 'Channel') {
|
||||||
|
resetLogin();
|
||||||
|
}
|
||||||
|
}, [loggingIn]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (loggingOut && details.type === 'Account') {
|
||||||
|
Logout(details.id)
|
||||||
|
.catch((error) => {
|
||||||
|
setError(error);
|
||||||
|
})
|
||||||
|
.finally(() => resetLogout());
|
||||||
|
} else if (loggingOut && details.type === 'Channel') {
|
||||||
|
resetLogout();
|
||||||
|
}
|
||||||
|
}, [loggingOut]);
|
||||||
|
|
||||||
|
const activatePage = () => {
|
||||||
|
switch (true) {
|
||||||
|
case details.type === 'Channel':
|
||||||
|
ActivateChannel(details.id).catch((error) => {
|
||||||
|
setError(error);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
case details.type === 'Account':
|
||||||
|
ActivateAccount(details.id).catch((error) => {
|
||||||
|
setError(error);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const deletePage = () => {
|
||||||
|
if (deleting || details.title !== deleteName) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setDeleting(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const resetDelete = () => {
|
||||||
|
setDeleteName('');
|
||||||
|
setDeleting(false);
|
||||||
|
setOpenDelete(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const submitEditApi = () => {
|
||||||
|
if (editingApi) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (editApi === '') {
|
||||||
|
setApiValid(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setEditingApi(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const closeEditApi = () => {
|
||||||
|
if (editingApi) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
resetEditApi();
|
||||||
|
};
|
||||||
|
|
||||||
|
const resetEditApi = () => {
|
||||||
|
setOpenApi(false);
|
||||||
|
setApiValid(true);
|
||||||
|
setEditApi('');
|
||||||
|
setEditingApi(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const login = () => {
|
||||||
|
if (loginUsername === '') {
|
||||||
|
setLoginUsernameValid(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (loginPassword === '') {
|
||||||
|
setLoginPasswordValid(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setLoggingIn(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const closeLogin = () => {
|
||||||
|
if (loggingIn) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setOpenLogin(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const resetLogin = () => {
|
||||||
|
setLoggingIn(false);
|
||||||
|
setOpenLogin(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const logout = () => {
|
||||||
|
setLoggingOut(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const closeLogout = () => {
|
||||||
|
if (loggingOut) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setOpenLogout(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const resetLogout = () => {
|
||||||
|
setLoggingOut(false);
|
||||||
|
setOpenLogout(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{openLogin && (
|
||||||
|
<Modal
|
||||||
|
cancelButton={'Cancel'}
|
||||||
|
onCancel={closeLogin}
|
||||||
|
onClose={closeLogin}
|
||||||
|
show={openLogin}
|
||||||
|
style={{
|
||||||
|
height: '480px',
|
||||||
|
minHeight: '480px',
|
||||||
|
width: '360px',
|
||||||
|
minWidth: '360px',
|
||||||
|
}}
|
||||||
|
submitButton={'Login'}
|
||||||
|
submitLoading={loggingIn}
|
||||||
|
onSubmit={login}
|
||||||
|
>
|
||||||
|
<ModalLogin
|
||||||
|
password={loginPassword}
|
||||||
|
passwordValid={loginPasswordValid}
|
||||||
|
updatePassword={updateLoginPassword}
|
||||||
|
username={loginUsername}
|
||||||
|
usernameValid={loginUsernameValid}
|
||||||
|
updateUsername={updateLoginUsername}
|
||||||
|
/>
|
||||||
|
</Modal>
|
||||||
|
)}
|
||||||
|
{openLogout && (
|
||||||
|
<SmallModal
|
||||||
|
cancelButton={'Cancel'}
|
||||||
|
onCancel={closeLogout}
|
||||||
|
onClose={closeLogout}
|
||||||
|
show={openLogout}
|
||||||
|
style={{ minWidth: '300px', maxWidth: '200px', maxHeight: '200px' }}
|
||||||
|
title={'Logout'}
|
||||||
|
message={'Are you sure you want to log out of ' + details.title + '?'}
|
||||||
|
submitButton={loggingOut ? 'Logging out...' : 'Logout'}
|
||||||
|
onSubmit={logout}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{error !== '' && (
|
||||||
|
<SmallModal
|
||||||
|
onClose={() => setError('')}
|
||||||
|
show={error !== ''}
|
||||||
|
style={{ minWidth: '300px', maxWidth: '200px', maxHeight: '200px' }}
|
||||||
|
title={'Error'}
|
||||||
|
message={error}
|
||||||
|
submitButton={'OK'}
|
||||||
|
onSubmit={() => setError('')}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{openDelete && (
|
||||||
|
<Modal
|
||||||
|
cancelButton={'Cancel'}
|
||||||
|
onCancel={resetDelete}
|
||||||
|
onClose={resetDelete}
|
||||||
|
deleteButton={deleting ? 'Deleting' : 'Delete'}
|
||||||
|
onDelete={deletePage}
|
||||||
|
deleteActive={details.title === deleteName}
|
||||||
|
pageName={details.title}
|
||||||
|
show={openDelete}
|
||||||
|
style={{
|
||||||
|
height: '350px',
|
||||||
|
minHeight: '350px',
|
||||||
|
width: '350px',
|
||||||
|
minWidth: '350px',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div className='modal-delete-page'>
|
||||||
|
<div className='modal-delete-page-header'>
|
||||||
|
<span className='modal-delete-page-title'>Delete page</span>
|
||||||
|
<span className='modal-delete-page-subtitle'>
|
||||||
|
Are you sure you want to delete <b>{details.title}</b>? This cannot
|
||||||
|
be undone. You must type '{details.title}' into the box to delete.
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div className='modal-delete-page-body'>
|
||||||
|
<div className='modal-delete-page-input'>
|
||||||
|
<input
|
||||||
|
className='modal-delete-page-input-text'
|
||||||
|
onChange={updateDeleteName}
|
||||||
|
placeholder={details.title}
|
||||||
|
type={'text'}
|
||||||
|
value={deleteName}
|
||||||
|
></input>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Modal>
|
||||||
|
)}
|
||||||
|
{openApi && (
|
||||||
|
<Modal
|
||||||
|
cancelButton={'Cancel'}
|
||||||
|
onCancel={closeEditApi}
|
||||||
|
onClose={closeEditApi}
|
||||||
|
show={openApi}
|
||||||
|
style={{
|
||||||
|
height: '480px',
|
||||||
|
minHeight: '480px',
|
||||||
|
width: '360px',
|
||||||
|
minWidth: '360px',
|
||||||
|
}}
|
||||||
|
submitButton={'Submit'}
|
||||||
|
submitLoading={editingApi}
|
||||||
|
onSubmit={submitEditApi}
|
||||||
|
>
|
||||||
|
<ModalEditApi
|
||||||
|
apiKey={editApi}
|
||||||
|
updateApiKey={updateEditApi}
|
||||||
|
apiValid={apiValid}
|
||||||
|
/>
|
||||||
|
</Modal>
|
||||||
|
)}
|
||||||
|
<div className='page-details'>
|
||||||
|
{details !== null && (
|
||||||
|
<>
|
||||||
|
<div className='page-details-header'>
|
||||||
|
<div className='page-details-header-left'>
|
||||||
|
<span className='page-details-header-title'>{details.title}</span>
|
||||||
|
<span className='page-details-header-type'>{details.type}</span>
|
||||||
|
</div>
|
||||||
|
<div className='page-details-header-right'>
|
||||||
|
{details.has_api && (
|
||||||
|
<button
|
||||||
|
className='page-details-header-button'
|
||||||
|
onClick={activatePage}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
className='page-details-header-icon'
|
||||||
|
src={active ? Pause : Play}
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
<button
|
||||||
|
className='page-details-header-button'
|
||||||
|
onClick={triggerSettings}
|
||||||
|
>
|
||||||
|
<img className='page-details-header-icon' src={Gear} />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{settings && (
|
||||||
|
<>
|
||||||
|
<div
|
||||||
|
className='page-details-settings-background'
|
||||||
|
onClick={triggerSettings}
|
||||||
|
></div>
|
||||||
|
<div className='page-details-settings'>
|
||||||
|
{details.type === 'Account' && (
|
||||||
|
<button
|
||||||
|
className='page-details-settings-button'
|
||||||
|
onClick={() => {
|
||||||
|
triggerSettings();
|
||||||
|
if (details.logged_in) {
|
||||||
|
setOpenLogout(true);
|
||||||
|
} else {
|
||||||
|
setOpenLogin(true);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{details.logged_in ? 'Logout' : 'Login'}
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
<button
|
||||||
|
className='page-details-settings-button'
|
||||||
|
onClick={() => {
|
||||||
|
triggerSettings();
|
||||||
|
setOpenApi(true);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Edit API key
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className='page-details-settings-button'
|
||||||
|
onClick={() => {
|
||||||
|
triggerSettings();
|
||||||
|
setOpenDelete(true);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Delete
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{active && activity !== null && (
|
||||||
|
<>
|
||||||
|
<PageActivity activity={activity} />
|
||||||
|
{live && (
|
||||||
|
<DetailsFooter
|
||||||
|
categories={activity.livestreams[0].categories}
|
||||||
|
dislikes={activity.livestreams[0].dislikes}
|
||||||
|
likes={activity.livestreams[0].likes}
|
||||||
|
title={activity.livestreams[0].title}
|
||||||
|
viewers={activity.livestreams[0].watching_now}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{!active && (
|
||||||
|
<div className='page-inactive'>
|
||||||
|
<span className='page-inactive-text'>
|
||||||
|
{details.has_api
|
||||||
|
? 'Press play to start API'
|
||||||
|
: 'Open settings to add API key'}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PageDetails;
|
||||||
|
|
||||||
|
function PageActivity(props) {
|
||||||
|
const eventDate = (event) => {
|
||||||
|
if (event.followed_on) {
|
||||||
|
return event.followed_on;
|
||||||
|
}
|
||||||
|
if (event.subscribed_on) {
|
||||||
|
return event.subscribed_on;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const sortEvents = () => {
|
||||||
|
let sorted = [
|
||||||
|
...props.activity.followers.recent_followers,
|
||||||
|
...props.activity.subscribers.recent_subscribers,
|
||||||
|
].sort((a, b) => (eventDate(a) < eventDate(b) ? 1 : -1));
|
||||||
|
|
||||||
|
return sorted;
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className='page-activity-header'>
|
||||||
|
<div className='page-activity-stat'>
|
||||||
|
<span className='page-activity-stat-title'>Followers:</span>
|
||||||
|
<span className='page-activity-stat-text'>
|
||||||
|
{countString(props.activity.followers.num_followers)}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div className='page-activity-stat'>
|
||||||
|
<span className='page-activity-stat-title'>Subscribers:</span>
|
||||||
|
<span className='page-activity-stat-text'>
|
||||||
|
{countString(props.activity.subscribers.num_subscribers)}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className='page-activity'>
|
||||||
|
<div className='page-activity-list'>
|
||||||
|
{sortEvents().map((event, index) => (
|
||||||
|
<PageEvent event={event} key={index} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function PageEvent(props) {
|
||||||
|
const dateDate = (date) => {
|
||||||
|
const options = { month: 'short' };
|
||||||
|
let month = new Intl.DateTimeFormat('en-US', options).format(date);
|
||||||
|
let day = date.getDate();
|
||||||
|
return month + ' ' + day;
|
||||||
|
};
|
||||||
|
|
||||||
|
const dateDay = (date) => {
|
||||||
|
let now = new Date();
|
||||||
|
let today = now.getDay();
|
||||||
|
switch (date.getDay()) {
|
||||||
|
case 0:
|
||||||
|
return 'Sunday';
|
||||||
|
case 1:
|
||||||
|
return 'Monday';
|
||||||
|
case 2:
|
||||||
|
return 'Tuesday';
|
||||||
|
case 3:
|
||||||
|
return 'Wednesday';
|
||||||
|
case 4:
|
||||||
|
return 'Thursday';
|
||||||
|
case 5:
|
||||||
|
return 'Friday';
|
||||||
|
case 6:
|
||||||
|
return 'Saturday';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const dateTime = (date) => {
|
||||||
|
let now = new Date();
|
||||||
|
let today = now.getDay();
|
||||||
|
let day = date.getDay();
|
||||||
|
|
||||||
|
if (today !== day) {
|
||||||
|
return dateDay(date);
|
||||||
|
}
|
||||||
|
|
||||||
|
let hours24 = date.getHours();
|
||||||
|
let hours = hours24 % 12 || 12;
|
||||||
|
|
||||||
|
let minutes = date.getMinutes();
|
||||||
|
if (minutes < 10) {
|
||||||
|
minutes = '0' + minutes;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mer = 'pm';
|
||||||
|
if (hours24 < 12) {
|
||||||
|
mer = 'am';
|
||||||
|
}
|
||||||
|
|
||||||
|
return hours + ':' + minutes + ' ' + mer;
|
||||||
|
};
|
||||||
|
|
||||||
|
const dateString = (d) => {
|
||||||
|
if (isNaN(Date.parse(d))) {
|
||||||
|
return 'Who knows?';
|
||||||
|
}
|
||||||
|
|
||||||
|
let now = new Date();
|
||||||
|
let date = new Date(d);
|
||||||
|
// Fix Rumble's timezone problem
|
||||||
|
date.setHours(date.getHours() - 4);
|
||||||
|
let diff = now - date;
|
||||||
|
switch (true) {
|
||||||
|
case diff < 0:
|
||||||
|
return 'In the future!?';
|
||||||
|
case diff < 60000:
|
||||||
|
return 'Now';
|
||||||
|
case diff < 3600000:
|
||||||
|
let minutes = Math.floor(diff / 1000 / 60);
|
||||||
|
let postfix = ' mins ago';
|
||||||
|
if (minutes == 1) {
|
||||||
|
postfix = ' min ago';
|
||||||
|
}
|
||||||
|
return minutes + postfix;
|
||||||
|
case diff < 86400000:
|
||||||
|
return dateTime(date);
|
||||||
|
case diff < 604800000:
|
||||||
|
return dateDay(date);
|
||||||
|
default:
|
||||||
|
return dateDate(date);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='page-event'>
|
||||||
|
<div className='page-event-left'>
|
||||||
|
{props.event.followed_on && <img className='page-event-icon' src={Heart}></img>}
|
||||||
|
{props.event.subscribed_on && <img className='page-event-icon' src={Star}></img>}
|
||||||
|
<div className='page-event-left-text'>
|
||||||
|
<span className='page-event-username'>{props.event.username}</span>
|
||||||
|
<span className='page-event-description'>
|
||||||
|
{props.event.followed_on && 'Followed you'}
|
||||||
|
{props.event.subscribed_on && 'Subscribed'}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<span className='page-event-date'>
|
||||||
|
{props.event.followed_on && dateString(props.event.followed_on)}
|
||||||
|
{props.event.subscribed_on && dateString(props.event.subscribed_on)}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function DetailsFooter(props) {
|
||||||
|
return (
|
||||||
|
<div className='page-details-footer'>
|
||||||
|
<span className='page-details-footer-title'>{props.title}</span>
|
||||||
|
<div className='page-details-footer-stats'>
|
||||||
|
<div className='page-details-footer-stat'>
|
||||||
|
<img className='page-details-footer-stat-icon' src={EyeRed} />
|
||||||
|
<span className='page-details-footer-stat-text-red'>
|
||||||
|
{countString(props.viewers)}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div className='page-details-footer-stat'>
|
||||||
|
<img className='page-details-footer-stat-icon' src={ThumbsUp} />
|
||||||
|
<span className='page-details-footer-stat-text'>
|
||||||
|
{countString(props.likes)}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div className='page-details-footer-stat'>
|
||||||
|
<img className='page-details-footer-stat-icon' src={ThumbsDown} />
|
||||||
|
<span className='page-details-footer-stat-text'>
|
||||||
|
{countString(props.dislikes)}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className='page-details-footer-categories'>
|
||||||
|
<span className='page-details-footer-category'>
|
||||||
|
{props.categories.primary.title}
|
||||||
|
</span>
|
||||||
|
<span className='page-details-footer-category'>
|
||||||
|
{props.categories.secondary.title}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function ModalEditApi(props) {
|
||||||
|
const [showKey, setShowKey] = useState(false);
|
||||||
|
const updateShowKey = () => setShowKey(!showKey);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='modal-add-account-channel'>
|
||||||
|
<div className='modal-add-account-channel-header'>
|
||||||
|
<span className='modal-add-account-channel-title'>Edit API Key</span>
|
||||||
|
<span className='modal-add-account-channel-subtitle'>Enter new API key below</span>
|
||||||
|
</div>
|
||||||
|
<div className='modal-add-account-channel-body'>
|
||||||
|
{props.apiValid === false ? (
|
||||||
|
<label className='modal-add-channel-label-warning'>
|
||||||
|
API KEY - Please enter a valid API key
|
||||||
|
</label>
|
||||||
|
) : (
|
||||||
|
<label className='modal-add-channel-label'>API KEY</label>
|
||||||
|
)}
|
||||||
|
<div className='modal-add-channel-key'>
|
||||||
|
<input
|
||||||
|
className='modal-add-channel-key-input'
|
||||||
|
onChange={props.updateApiKey}
|
||||||
|
placeholder={'Enter API key'}
|
||||||
|
type={showKey ? 'text' : 'password'}
|
||||||
|
value={props.apiKey}
|
||||||
|
></input>
|
||||||
|
<button className='modal-add-channel-key-show' onClick={updateShowKey}>
|
||||||
|
<img
|
||||||
|
className='modal-add-channel-key-show-icon'
|
||||||
|
src={showKey ? EyeSlash : Eye}
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<span className='modal-add-channel-description'>API KEYS SHOULD LOOK LIKE</span>
|
||||||
|
<span className='modal-add-channel-description-subtext'>
|
||||||
|
https://rumble.com/-livestream-api/get-data?key=really-long_string-of_random-characters
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div></div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function ModalLogin(props) {
|
||||||
|
const [showPassword, setShowPassword] = useState(false);
|
||||||
|
const updateShowPassword = () => setShowPassword(!showPassword);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='modal-add-account-channel'>
|
||||||
|
<div className='modal-add-account-channel-header'>
|
||||||
|
<span className='modal-add-account-channel-title'>Login</span>
|
||||||
|
<span className='modal-add-account-channel-subtitle'>
|
||||||
|
Log into your Rumble account
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div className='modal-add-account-channel-body'>
|
||||||
|
{props.usernameValid === false ? (
|
||||||
|
<label className='modal-add-account-channel-label-warning'>
|
||||||
|
USERNAME - Please enter a valid username
|
||||||
|
</label>
|
||||||
|
) : (
|
||||||
|
<label className='modal-add-account-channel-label'>USERNAME</label>
|
||||||
|
)}
|
||||||
|
<div className='modal-add-account-channel-input'>
|
||||||
|
<input
|
||||||
|
className='modal-add-account-channel-input-text'
|
||||||
|
onChange={!props.loading && props.updateUsername}
|
||||||
|
placeholder={'Username'}
|
||||||
|
type={'text'}
|
||||||
|
value={props.username}
|
||||||
|
></input>
|
||||||
|
</div>
|
||||||
|
{props.passwordValid === false ? (
|
||||||
|
<label className='modal-add-account-channel-label-warning'>
|
||||||
|
PASSWORD - Please enter a valid password
|
||||||
|
</label>
|
||||||
|
) : (
|
||||||
|
<label className='modal-add-account-channel-label'>PASSWORD</label>
|
||||||
|
)}
|
||||||
|
<div className='modal-add-account-channel-input'>
|
||||||
|
<input
|
||||||
|
className='modal-add-account-channel-input-password'
|
||||||
|
onChange={!props.loading && props.updatePassword}
|
||||||
|
placeholder={'Password'}
|
||||||
|
type={showPassword ? 'text' : 'password'}
|
||||||
|
value={props.password}
|
||||||
|
></input>
|
||||||
|
<button
|
||||||
|
className='modal-add-account-channel-input-show'
|
||||||
|
onClick={updateShowPassword}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
className='modal-add-account-channel-input-show-icon'
|
||||||
|
src={showPassword ? EyeSlash : Eye}
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div></div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
|
@ -1,5 +1,4 @@
|
||||||
|
.page-sidebar {
|
||||||
.channel-sidebar {
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background-color: #061726;
|
background-color: #061726;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -7,18 +6,19 @@
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
padding: 0px 10px;
|
padding: 0px 10px;
|
||||||
|
width: 60px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.channel-sidebar-account-list {
|
.page-sidebar-account-list {
|
||||||
border-top: 2px solid #273848;
|
border-top: 2px solid #273848;
|
||||||
padding-bottom: 10px;
|
padding-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.channel-sidebar-body {
|
.page-sidebar-body {
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.channel-sidebar-button {
|
.page-sidebar-button {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background-color: #061726;
|
background-color: #061726;
|
||||||
border: none;
|
border: none;
|
||||||
|
@ -27,27 +27,31 @@
|
||||||
padding: 0px;
|
padding: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.channel-sidebar-button:hover {
|
.page-sidebar-button:hover {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.channel-sidebar-button-icon {
|
.page-sidebar-button-icon {
|
||||||
height: 60px;
|
height: 60px;
|
||||||
width: 60px;
|
width: 60px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.channel-sidebar-footer {
|
.page-sidebar-footer {
|
||||||
padding-bottom: 10px;
|
padding-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.channel-sidebar-icon {
|
.page-sidebar-icon {
|
||||||
height: 60px;
|
height: 60px;
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 60px;
|
width: 60px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.channel-sidebar-icon-account {
|
.page-sidebar-icon:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-sidebar-icon-account {
|
||||||
bottom: 0px;
|
bottom: 0px;
|
||||||
height: 24px;
|
height: 24px;
|
||||||
left: 36px;
|
left: 36px;
|
||||||
|
@ -55,7 +59,7 @@
|
||||||
width: 24px;
|
width: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.channel-sidebar-icon-hover {
|
.page-sidebar-icon-hover {
|
||||||
background-color: #061726;
|
background-color: #061726;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
color: black;
|
color: black;
|
||||||
|
@ -64,7 +68,7 @@
|
||||||
/* transform: translate(75px, -50px); */
|
/* transform: translate(75px, -50px); */
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
}
|
}
|
||||||
.channel-sidebar-icon-hover:before {
|
.page-sidebar-icon-hover:before {
|
||||||
content:"";
|
content:"";
|
||||||
position: absolute;
|
position: absolute;
|
||||||
width: 0;
|
width: 0;
|
||||||
|
@ -75,34 +79,35 @@
|
||||||
margin: 7px 0 0 -13px;
|
margin: 7px 0 0 -13px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.channel-sidebar-icon-hover-text {
|
.page-sidebar-icon-hover-text {
|
||||||
color: white;
|
color: white;
|
||||||
font-family: sans-serif;
|
font-family: sans-serif;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.channel-sidebar-icon-image {
|
.page-sidebar-icon-image {
|
||||||
/* border: 3px solid #85c742; */
|
/* border: 3px solid #85c742; */
|
||||||
/* border: 3px solid #ec0; */
|
/* border: 3px solid #ec0; */
|
||||||
border: 3px solid #f23160;
|
/* border: 3px solid #f23160; */
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
height: 54px;
|
height: 54px;
|
||||||
transition: border-radius 0.25s;
|
transition: border-radius 0.25s;
|
||||||
width: 54px;
|
width: 54px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.channel-sidebar-icon-image:hover {
|
.page-sidebar-icon-image:hover {
|
||||||
border-radius: 30%;
|
border-radius: 30%;
|
||||||
transition: border-radius 0.25s;
|
transition: border-radius 0.25s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.channel-sidebar-icon-initial {
|
.page-sidebar-icon-initial {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background-color: #3377cc;
|
background-color: #3377cc;
|
||||||
|
/* border: 3px solid #3377cc; */
|
||||||
/* border: 3px solid #85c742; */
|
/* border: 3px solid #85c742; */
|
||||||
/* border: 3px solid #ec0; */
|
/* border: 3px solid #ec0; */
|
||||||
border: 3px solid #f23160;
|
/* border: 3px solid #f23160; */
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
color: #eee;
|
color: #eee;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -115,7 +120,7 @@
|
||||||
width: 54px;
|
width: 54px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.channel-sidebar-icon-initial:hover {
|
.page-sidebar-icon-initial:hover {
|
||||||
border-radius: 30%;
|
border-radius: 30%;
|
||||||
transition: border-radius 0.25s;
|
transition: border-radius 0.25s;
|
||||||
}
|
}
|
|
@ -1,17 +1,38 @@
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { Modal, SmallModal } from './Modal';
|
import { Modal, SmallModal } from './Modal';
|
||||||
import { AccountList, AddChannel, Login } from '../../wailsjs/go/main/App';
|
import {
|
||||||
|
AccountList,
|
||||||
|
AddPage,
|
||||||
|
Login,
|
||||||
|
OpenAccount,
|
||||||
|
OpenChannel,
|
||||||
|
PageStatus,
|
||||||
|
} from '../../wailsjs/go/main/App';
|
||||||
|
import { EventsOff, EventsOn } from '../../wailsjs/runtime/runtime';
|
||||||
|
|
||||||
import { ChevronRight, CircleGreenBackground, Eye, EyeSlash, PlusCircle } from '../assets';
|
import {
|
||||||
import './ChannelSideBar.css';
|
ChevronRight,
|
||||||
|
CircleGreenBackground,
|
||||||
|
CircleRedBackground,
|
||||||
|
Eye,
|
||||||
|
EyeSlash,
|
||||||
|
PlusCircle,
|
||||||
|
} from '../assets';
|
||||||
|
import './PageSideBar.css';
|
||||||
|
|
||||||
function ChannelSideBar(props) {
|
function PageSideBar(props) {
|
||||||
const [accounts, setAccounts] = useState({});
|
const [accounts, setAccounts] = useState({});
|
||||||
const [error, setError] = useState('');
|
const [error, setError] = useState('');
|
||||||
const [addOpen, setAddOpen] = useState(false);
|
const [addOpen, setAddOpen] = useState(false);
|
||||||
const [refresh, setRefresh] = useState(false);
|
const [refresh, setRefresh] = useState(false);
|
||||||
const [scrollY, setScrollY] = useState(0);
|
const [scrollY, setScrollY] = useState(0);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
EventsOn('PageSideBarAccounts', (event) => {
|
||||||
|
setAccounts(event);
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
AccountList()
|
AccountList()
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
|
@ -38,8 +59,17 @@ function ChannelSideBar(props) {
|
||||||
setScrollY(event.target.scrollTop);
|
setScrollY(event.target.scrollTop);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const openAccount = (account) => {
|
||||||
|
OpenAccount(account.id).catch((error) => setError(error));
|
||||||
|
};
|
||||||
|
|
||||||
|
const openChannel = (channel) => {
|
||||||
|
OpenChannel(channel.id).catch((error) => setError(error));
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
{addOpen && (
|
||||||
<ModalAdd
|
<ModalAdd
|
||||||
onClose={() => setAddOpen(false)}
|
onClose={() => setAddOpen(false)}
|
||||||
onRefresh={() => {
|
onRefresh={() => {
|
||||||
|
@ -47,18 +77,21 @@ function ChannelSideBar(props) {
|
||||||
}}
|
}}
|
||||||
show={addOpen}
|
show={addOpen}
|
||||||
/>
|
/>
|
||||||
<div className='channel-sidebar'>
|
)}
|
||||||
<div className='channel-sidebar-body' onScroll={handleScroll}>
|
<div className='page-sidebar'>
|
||||||
|
<div className='page-sidebar-body' onScroll={handleScroll}>
|
||||||
{sortAccounts().map((account, index) => (
|
{sortAccounts().map((account, index) => (
|
||||||
<AccountChannels
|
<AccountChannels
|
||||||
account={accounts[account]}
|
account={accounts[account]}
|
||||||
key={index}
|
key={index}
|
||||||
|
openAccount={openAccount}
|
||||||
|
openChannel={openChannel}
|
||||||
scrollY={scrollY}
|
scrollY={scrollY}
|
||||||
top={index === 0}
|
top={index === 0}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
<div className='channel-sidebar-footer'>
|
<div className='page-sidebar-footer'>
|
||||||
<ButtonIcon
|
<ButtonIcon
|
||||||
hoverText={'Add an account/channel'}
|
hoverText={'Add an account/channel'}
|
||||||
onClick={() => setAddOpen(true)}
|
onClick={() => setAddOpen(true)}
|
||||||
|
@ -70,7 +103,7 @@ function ChannelSideBar(props) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default ChannelSideBar;
|
export default PageSideBar;
|
||||||
|
|
||||||
function AccountChannels(props) {
|
function AccountChannels(props) {
|
||||||
const sortChannels = () => {
|
const sortChannels = () => {
|
||||||
|
@ -84,12 +117,24 @@ function AccountChannels(props) {
|
||||||
if (props.account.account !== undefined) {
|
if (props.account.account !== undefined) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className='channel-sidebar-account-list'
|
className='page-sidebar-account-list'
|
||||||
style={props.top ? { borderTop: 'none' } : {}}
|
style={props.top ? { borderTop: 'none' } : {}}
|
||||||
>
|
>
|
||||||
<AccountIcon account={props.account.account} key={0} scrollY={props.scrollY} />
|
<button
|
||||||
|
className='page-sidebar-button'
|
||||||
|
key={0}
|
||||||
|
onClick={() => props.openAccount(props.account.account)}
|
||||||
|
>
|
||||||
|
<AccountIcon account={props.account.account} scrollY={props.scrollY} />
|
||||||
|
</button>
|
||||||
{sortChannels().map((channel, index) => (
|
{sortChannels().map((channel, index) => (
|
||||||
<ChannelIcon channel={channel} key={index + 1} scrollY={props.scrollY} />
|
<button
|
||||||
|
className='page-sidebar-button'
|
||||||
|
key={index + 1}
|
||||||
|
onClick={() => props.openChannel(channel)}
|
||||||
|
>
|
||||||
|
<ChannelIcon channel={channel} scrollY={props.scrollY} />
|
||||||
|
</button>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -97,25 +142,82 @@ function AccountChannels(props) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function AccountIcon(props) {
|
function AccountIcon(props) {
|
||||||
|
const [apiActive, setApiActive] = useState(false);
|
||||||
const [hover, setHover] = useState(false);
|
const [hover, setHover] = useState(false);
|
||||||
|
const [isLive, setIsLive] = useState(false);
|
||||||
|
const [loggedIn, setLoggedIn] = useState(props.account.cookies !== null);
|
||||||
|
const [username, setUsername] = useState(props.account.username);
|
||||||
|
|
||||||
|
const iconBorder = () => {
|
||||||
|
if (!apiActive) {
|
||||||
|
return '3px solid #3377cc';
|
||||||
|
}
|
||||||
|
if (isLive) {
|
||||||
|
return '3px solid #85c742';
|
||||||
|
} else {
|
||||||
|
return '3px solid #f23160';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const pageName = (name) => {
|
||||||
|
if (name === undefined) return;
|
||||||
|
return '/user/' + name;
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (username !== props.account.username) {
|
||||||
|
EventsOff(
|
||||||
|
'ApiActive-' + pageName(username),
|
||||||
|
'LoggedIn-' + pageName(username),
|
||||||
|
'PageLive-' + pageName(username)
|
||||||
|
);
|
||||||
|
setApiActive(false);
|
||||||
|
setIsLive(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
EventsOn('ApiActive-' + pageName(props.account.username), (event) => {
|
||||||
|
setApiActive(event);
|
||||||
|
});
|
||||||
|
|
||||||
|
EventsOn('LoggedIn-' + pageName(props.account.username), (event) => {
|
||||||
|
setLoggedIn(event);
|
||||||
|
});
|
||||||
|
|
||||||
|
EventsOn('PageLive-' + pageName(props.account.username), (event) => {
|
||||||
|
setIsLive(event);
|
||||||
|
});
|
||||||
|
|
||||||
|
setUsername(props.account.username);
|
||||||
|
}, [props.account.username]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (username !== '') {
|
||||||
|
PageStatus(pageName(username));
|
||||||
|
}
|
||||||
|
}, [username]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className='channel-sidebar-icon'
|
className='page-sidebar-icon'
|
||||||
onMouseEnter={() => setHover(true)}
|
onMouseEnter={() => setHover(true)}
|
||||||
onMouseLeave={() => setHover(false)}
|
onMouseLeave={() => setHover(false)}
|
||||||
>
|
>
|
||||||
{props.account.profile_image === null ? (
|
{props.account.profile_image === null ? (
|
||||||
<span className='channel-sidebar-icon-initial'>
|
<span className='page-sidebar-icon-initial' style={{ border: iconBorder() }}>
|
||||||
{props.account.username[0].toUpperCase()}
|
{props.account.username[0].toUpperCase()}
|
||||||
</span>
|
</span>
|
||||||
) : (
|
) : (
|
||||||
<img className='channel-sidebar-icon-image' src={props.account.profile_image} />
|
<img
|
||||||
)}
|
className='page-sidebar-icon-image'
|
||||||
<img className='channel-sidebar-icon-account' src={CircleGreenBackground} />
|
src={props.account.profile_image}
|
||||||
{hover && (
|
style={{ border: iconBorder() }}
|
||||||
<HoverName name={'/user/' + props.account.username} scrollY={props.scrollY} />
|
/>
|
||||||
)}
|
)}
|
||||||
|
<img
|
||||||
|
className='page-sidebar-icon-account'
|
||||||
|
src={loggedIn ? CircleGreenBackground : CircleRedBackground}
|
||||||
|
/>
|
||||||
|
{hover && <HoverName name={pageName(username)} scrollY={props.scrollY} />}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -125,12 +227,12 @@ function ButtonIcon(props) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className='channel-sidebar-icon'
|
className='page-sidebar-icon'
|
||||||
onMouseEnter={() => setHover(true)}
|
onMouseEnter={() => setHover(true)}
|
||||||
onMouseLeave={() => setHover(false)}
|
onMouseLeave={() => setHover(false)}
|
||||||
>
|
>
|
||||||
<button className='channel-sidebar-button' onClick={props.onClick}>
|
<button className='page-sidebar-button' onClick={props.onClick}>
|
||||||
<img className='channel-sidebar-button-icon' src={PlusCircle} />
|
<img className='page-sidebar-button-icon' src={PlusCircle} />
|
||||||
</button>
|
</button>
|
||||||
{hover && <HoverName name={props.hoverText} scrollY={props.scrollY} />}
|
{hover && <HoverName name={props.hoverText} scrollY={props.scrollY} />}
|
||||||
</div>
|
</div>
|
||||||
|
@ -138,26 +240,69 @@ function ButtonIcon(props) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function ChannelIcon(props) {
|
function ChannelIcon(props) {
|
||||||
|
const [apiActive, setApiActive] = useState(false);
|
||||||
|
const [channelName, setChannelName] = useState(props.channel.name);
|
||||||
const [hover, setHover] = useState(false);
|
const [hover, setHover] = useState(false);
|
||||||
|
const [isLive, setIsLive] = useState(false);
|
||||||
|
|
||||||
|
const iconBorder = () => {
|
||||||
|
if (!apiActive) {
|
||||||
|
return '3px solid #3377cc';
|
||||||
|
}
|
||||||
|
if (isLive) {
|
||||||
|
return '3px solid #85c742';
|
||||||
|
} else {
|
||||||
|
return '3px solid #f23160';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const pageName = (name) => {
|
||||||
|
if (name === undefined) return;
|
||||||
|
return '/c/' + name.replace(/\s/g, '');
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (channelName !== props.channel.name) {
|
||||||
|
EventsOff('PageLive-' + pageName(channelName), 'ApiActive-' + pageName(channelName));
|
||||||
|
setApiActive(false);
|
||||||
|
setIsLive(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
EventsOn('PageLive-' + pageName(props.channel.name), (event) => {
|
||||||
|
setIsLive(event);
|
||||||
|
});
|
||||||
|
|
||||||
|
EventsOn('ApiActive-' + pageName(props.channel.name), (event) => {
|
||||||
|
setApiActive(event);
|
||||||
|
});
|
||||||
|
|
||||||
|
setChannelName(props.channel.name);
|
||||||
|
}, [props.channel.name]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (channelName !== '') {
|
||||||
|
PageStatus(pageName(channelName));
|
||||||
|
}
|
||||||
|
}, [channelName]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className='channel-sidebar-icon'
|
className='page-sidebar-icon'
|
||||||
onMouseEnter={() => setHover(true)}
|
onMouseEnter={() => setHover(true)}
|
||||||
onMouseLeave={() => setHover(false)}
|
onMouseLeave={() => setHover(false)}
|
||||||
>
|
>
|
||||||
{props.channel.profile_image === null ? (
|
{props.channel.profile_image === null ? (
|
||||||
<span className='channel-sidebar-icon-initial'>
|
<span className='page-sidebar-icon-initial' style={{ border: iconBorder() }}>
|
||||||
{props.channel.name[0].toUpperCase()}
|
{props.channel.name[0].toUpperCase()}
|
||||||
</span>
|
</span>
|
||||||
) : (
|
) : (
|
||||||
<img className='channel-sidebar-icon-image' src={props.channel.profile_image} />
|
<img
|
||||||
)}
|
className='page-sidebar-icon-image'
|
||||||
{hover && (
|
src={props.channel.profile_image}
|
||||||
<HoverName
|
style={{ border: iconBorder() }}
|
||||||
name={'/c/' + props.channel.name.replace(/\s/g, '')}
|
|
||||||
scrollY={props.scrollY}
|
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
{hover && <HoverName name={pageName(channelName)} scrollY={props.scrollY} />}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -165,10 +310,10 @@ function ChannelIcon(props) {
|
||||||
function HoverName(props) {
|
function HoverName(props) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className='channel-sidebar-icon-hover'
|
className='page-sidebar-icon-hover'
|
||||||
style={{ transform: 'translate(75px, -' + (50 + props.scrollY) + 'px)' }}
|
style={{ transform: 'translate(75px, -' + (50 + props.scrollY) + 'px)' }}
|
||||||
>
|
>
|
||||||
<span className='channel-sidebar-icon-hover-text'>{props.name}</span>
|
<span className='page-sidebar-icon-hover-text'>{props.name}</span>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -220,7 +365,7 @@ function ModalAdd(props) {
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (addChannelLoading) {
|
if (addChannelLoading) {
|
||||||
AddChannel(channelKey)
|
AddPage(channelKey)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
reset();
|
reset();
|
||||||
props.onClose();
|
props.onClose();
|
||||||
|
@ -318,6 +463,7 @@ function ModalAdd(props) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
{error !== '' && (
|
||||||
<SmallModal
|
<SmallModal
|
||||||
onClose={() => setError('')}
|
onClose={() => setError('')}
|
||||||
show={error !== ''}
|
show={error !== ''}
|
||||||
|
@ -327,6 +473,7 @@ function ModalAdd(props) {
|
||||||
submitButton={'OK'}
|
submitButton={'OK'}
|
||||||
onSubmit={() => setError('')}
|
onSubmit={() => setError('')}
|
||||||
/>
|
/>
|
||||||
|
)}
|
||||||
<Modal
|
<Modal
|
||||||
cancelButton={stage !== 'start' ? 'Back' : ''}
|
cancelButton={stage !== 'start' ? 'Back' : ''}
|
||||||
onCancel={back}
|
onCancel={back}
|
|
@ -1,12 +1,16 @@
|
||||||
|
import { useState } from 'react';
|
||||||
|
|
||||||
import { CircleGreenBackground, Heart } from '../assets';
|
import { CircleGreenBackground, Heart } from '../assets';
|
||||||
import ChannelSideBar from '../components/ChannelSideBar';
|
import PageDetails from '../components/PageDetails';
|
||||||
|
import PageSideBar from '../components/PageSideBar';
|
||||||
import './Dashboard.css';
|
import './Dashboard.css';
|
||||||
|
|
||||||
function Dashboard() {
|
function Dashboard() {
|
||||||
return (
|
return (
|
||||||
<div className='dashboard'>
|
<div className='dashboard'>
|
||||||
<ChannelSideBar />
|
<PageSideBar />
|
||||||
<div style={{ backgroundColor: '#1f2e3c', width: '100%', height: '100%' }}></div>
|
<PageDetails />
|
||||||
|
<div style={{ backgroundColor: '#344453', width: '100%', height: '100%' }}></div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
10
v1/go.mod
|
@ -6,7 +6,7 @@ toolchain go1.22.0
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/mattn/go-sqlite3 v1.14.22
|
github.com/mattn/go-sqlite3 v1.14.22
|
||||||
github.com/tylertravisty/rumble-livestream-lib-go v0.3.4
|
github.com/tylertravisty/rumble-livestream-lib-go v0.3.5
|
||||||
github.com/wailsapp/wails/v2 v2.8.0
|
github.com/wailsapp/wails/v2 v2.8.0
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ require (
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
github.com/r3labs/sse/v2 v2.10.0 // indirect
|
github.com/r3labs/sse/v2 v2.10.0 // indirect
|
||||||
github.com/rivo/uniseg v0.4.4 // indirect
|
github.com/rivo/uniseg v0.4.4 // indirect
|
||||||
github.com/robertkrimen/otto v0.2.1 // indirect
|
github.com/robertkrimen/otto v0.3.0 // indirect
|
||||||
github.com/samber/lo v1.38.1 // indirect
|
github.com/samber/lo v1.38.1 // indirect
|
||||||
github.com/tkrajina/go-reflector v0.5.6 // indirect
|
github.com/tkrajina/go-reflector v0.5.6 // indirect
|
||||||
github.com/tylertravisty/go-utils v0.0.0-20230524204414-6893ae548909 // indirect
|
github.com/tylertravisty/go-utils v0.0.0-20230524204414-6893ae548909 // indirect
|
||||||
|
@ -36,10 +36,10 @@ require (
|
||||||
github.com/valyala/fasttemplate v1.2.2 // indirect
|
github.com/valyala/fasttemplate v1.2.2 // indirect
|
||||||
github.com/wailsapp/go-webview2 v1.0.10 // indirect
|
github.com/wailsapp/go-webview2 v1.0.10 // indirect
|
||||||
github.com/wailsapp/mimetype v1.4.1 // indirect
|
github.com/wailsapp/mimetype v1.4.1 // indirect
|
||||||
golang.org/x/crypto v0.18.0 // indirect
|
golang.org/x/crypto v0.21.0 // indirect
|
||||||
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 // indirect
|
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 // indirect
|
||||||
golang.org/x/net v0.20.0 // indirect
|
golang.org/x/net v0.22.0 // indirect
|
||||||
golang.org/x/sys v0.16.0 // indirect
|
golang.org/x/sys v0.18.0 // indirect
|
||||||
golang.org/x/text v0.14.0 // indirect
|
golang.org/x/text v0.14.0 // indirect
|
||||||
gopkg.in/cenkalti/backoff.v1 v1.1.0 // indirect
|
gopkg.in/cenkalti/backoff.v1 v1.1.0 // indirect
|
||||||
gopkg.in/sourcemap.v1 v1.0.5 // indirect
|
gopkg.in/sourcemap.v1 v1.0.5 // indirect
|
||||||
|
|
20
v1/go.sum
|
@ -48,8 +48,8 @@ github.com/r3labs/sse/v2 v2.10.0/go.mod h1:Igau6Whc+F17QUgML1fYe1VPZzTV6EMCnYktE
|
||||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||||
github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis=
|
github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis=
|
||||||
github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||||
github.com/robertkrimen/otto v0.2.1 h1:FVP0PJ0AHIjC+N4pKCG9yCDz6LHNPCwi/GKID5pGGF0=
|
github.com/robertkrimen/otto v0.3.0 h1:5RI+8860NSxvXywDY9ddF5HcPw0puRsd8EgbXV0oqRE=
|
||||||
github.com/robertkrimen/otto v0.2.1/go.mod h1:UPwtJ1Xu7JrLcZjNWN8orJaM5n5YEtqL//farB5FlRY=
|
github.com/robertkrimen/otto v0.3.0/go.mod h1:uW9yN1CYflmUQYvAMS0m+ZiNo3dMzRUDQJX0jWbzgxw=
|
||||||
github.com/samber/lo v1.38.1 h1:j2XEAqXKb09Am4ebOg31SpvzUTTs6EN3VfgeLUhPdXM=
|
github.com/samber/lo v1.38.1 h1:j2XEAqXKb09Am4ebOg31SpvzUTTs6EN3VfgeLUhPdXM=
|
||||||
github.com/samber/lo v1.38.1/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA=
|
github.com/samber/lo v1.38.1/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
@ -60,8 +60,8 @@ github.com/tkrajina/go-reflector v0.5.6 h1:hKQ0gyocG7vgMD2M3dRlYN6WBBOmdoOzJ6njQ
|
||||||
github.com/tkrajina/go-reflector v0.5.6/go.mod h1:ECbqLgccecY5kPmPmXg1MrHW585yMcDkVl6IvJe64T4=
|
github.com/tkrajina/go-reflector v0.5.6/go.mod h1:ECbqLgccecY5kPmPmXg1MrHW585yMcDkVl6IvJe64T4=
|
||||||
github.com/tylertravisty/go-utils v0.0.0-20230524204414-6893ae548909 h1:xrjIFqzGQXlCrCdMPpW6+SodGFSlrQ3ZNUCr3f5tF1g=
|
github.com/tylertravisty/go-utils v0.0.0-20230524204414-6893ae548909 h1:xrjIFqzGQXlCrCdMPpW6+SodGFSlrQ3ZNUCr3f5tF1g=
|
||||||
github.com/tylertravisty/go-utils v0.0.0-20230524204414-6893ae548909/go.mod h1:2W31Jhs9YSy7y500wsCOW0bcamGi9foQV1CKrfvfTxk=
|
github.com/tylertravisty/go-utils v0.0.0-20230524204414-6893ae548909/go.mod h1:2W31Jhs9YSy7y500wsCOW0bcamGi9foQV1CKrfvfTxk=
|
||||||
github.com/tylertravisty/rumble-livestream-lib-go v0.3.4 h1:VPKelrC3hesJlbqdByMkUhbEubFx80T5FNC60JKrEfw=
|
github.com/tylertravisty/rumble-livestream-lib-go v0.3.5 h1:mAf4oYuQ55pXTPsIMVztOlYM8oGsBgsNMJvel2VLgsQ=
|
||||||
github.com/tylertravisty/rumble-livestream-lib-go v0.3.4/go.mod h1:rUET5uInouMfB4ekqdGiYeoN5ibOdzU9cCgRE0i57Wg=
|
github.com/tylertravisty/rumble-livestream-lib-go v0.3.5/go.mod h1:rUET5uInouMfB4ekqdGiYeoN5ibOdzU9cCgRE0i57Wg=
|
||||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||||
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
||||||
|
@ -74,14 +74,14 @@ github.com/wailsapp/mimetype v1.4.1/go.mod h1:9aV5k31bBOv5z6u+QP8TltzvNGJPmNJD4X
|
||||||
github.com/wailsapp/wails/v2 v2.8.0 h1:b2NNn99uGPiN6P5bDsnPwOJZWtAOUhNLv7Vl+YxMTr4=
|
github.com/wailsapp/wails/v2 v2.8.0 h1:b2NNn99uGPiN6P5bDsnPwOJZWtAOUhNLv7Vl+YxMTr4=
|
||||||
github.com/wailsapp/wails/v2 v2.8.0/go.mod h1:EFUGWkUX3KofO4fmKR/GmsLy3HhPH7NbyOEaMt8lBF0=
|
github.com/wailsapp/wails/v2 v2.8.0/go.mod h1:EFUGWkUX3KofO4fmKR/GmsLy3HhPH7NbyOEaMt8lBF0=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
|
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
|
||||||
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
|
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
|
||||||
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 h1:k/i9J1pBpvlfR+9QsetwPyERsqu1GIbi967PQMq3Ivc=
|
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 h1:k/i9J1pBpvlfR+9QsetwPyERsqu1GIbi967PQMq3Ivc=
|
||||||
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w=
|
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w=
|
||||||
golang.org/x/net v0.0.0-20191116160921-f9c825593386/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20191116160921-f9c825593386/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
|
golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc=
|
||||||
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
|
golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
@ -93,8 +93,8 @@ golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||||
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
|
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
|
||||||
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
|
257
v1/internal/api/api.go
Normal file
|
@ -0,0 +1,257 @@
|
||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
rumblelivestreamlib "github.com/tylertravisty/rumble-livestream-lib-go"
|
||||||
|
"github.com/wailsapp/wails/v2/pkg/runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Api struct {
|
||||||
|
callers map[string]*caller
|
||||||
|
callersMu sync.Mutex
|
||||||
|
ctx context.Context
|
||||||
|
display string
|
||||||
|
displayMu sync.Mutex
|
||||||
|
logError *log.Logger
|
||||||
|
logInfo *log.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
type caller struct {
|
||||||
|
cancel context.CancelFunc
|
||||||
|
cancelMu sync.Mutex
|
||||||
|
display bool
|
||||||
|
displayMu sync.Mutex
|
||||||
|
interval time.Duration
|
||||||
|
name string
|
||||||
|
response *rumblelivestreamlib.LivestreamResponse
|
||||||
|
responseMu sync.Mutex
|
||||||
|
url string
|
||||||
|
}
|
||||||
|
|
||||||
|
type event struct {
|
||||||
|
close bool
|
||||||
|
err error
|
||||||
|
name string
|
||||||
|
resp *rumblelivestreamlib.LivestreamResponse
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewApi(logError *log.Logger, logInfo *log.Logger) *Api {
|
||||||
|
return &Api{logError: logError, logInfo: logInfo}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Api) Response(name string) *rumblelivestreamlib.LivestreamResponse {
|
||||||
|
a.callersMu.Lock()
|
||||||
|
defer a.callersMu.Unlock()
|
||||||
|
caller, exists := a.callers[name]
|
||||||
|
if !exists {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
caller.responseMu.Lock()
|
||||||
|
defer caller.responseMu.Unlock()
|
||||||
|
|
||||||
|
copy := *caller.response
|
||||||
|
return ©
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Api) Display(name string) error {
|
||||||
|
a.displayMu.Lock()
|
||||||
|
defer a.displayMu.Unlock()
|
||||||
|
if name == a.display {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
a.callersMu.Lock()
|
||||||
|
defer a.callersMu.Unlock()
|
||||||
|
|
||||||
|
if a.display != "" {
|
||||||
|
displaying, exists := a.callers[a.display]
|
||||||
|
if !exists {
|
||||||
|
return pkgErr("", fmt.Errorf("displaying caller does not exist: %s", a.display))
|
||||||
|
}
|
||||||
|
displaying.displayMu.Lock()
|
||||||
|
displaying.display = false
|
||||||
|
displaying.displayMu.Unlock()
|
||||||
|
a.display = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
caller, exists := a.callers[name]
|
||||||
|
if !exists {
|
||||||
|
// return pkgErr("", fmt.Errorf("caller does not exist: %s", name))
|
||||||
|
runtime.EventsEmit(a.ctx, "PageActive", false)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
caller.displayMu.Lock()
|
||||||
|
caller.display = true
|
||||||
|
caller.displayMu.Unlock()
|
||||||
|
|
||||||
|
a.display = name
|
||||||
|
|
||||||
|
a.handleResponse(caller)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Api) Startup(ctx context.Context) {
|
||||||
|
a.ctx = ctx
|
||||||
|
a.callers = map[string]*caller{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Api) Shutdown() error {
|
||||||
|
for _, caller := range a.callers {
|
||||||
|
caller.cancelMu.Lock()
|
||||||
|
if caller.cancel != nil {
|
||||||
|
caller.cancel()
|
||||||
|
}
|
||||||
|
caller.cancelMu.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Api) Start(name string, url string, interval time.Duration) error {
|
||||||
|
if name == "" {
|
||||||
|
return fmt.Errorf("name is empty")
|
||||||
|
}
|
||||||
|
if url == "" {
|
||||||
|
return fmt.Errorf("url is empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
a.callersMu.Lock()
|
||||||
|
defer a.callersMu.Unlock()
|
||||||
|
if _, active := a.callers[name]; active {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
caller := &caller{
|
||||||
|
cancel: cancel,
|
||||||
|
interval: interval,
|
||||||
|
name: name,
|
||||||
|
url: url,
|
||||||
|
}
|
||||||
|
a.callers[name] = caller
|
||||||
|
go a.run(ctx, caller)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Api) run(ctx context.Context, caller *caller) {
|
||||||
|
client := &rumblelivestreamlib.Client{StreamKey: caller.url}
|
||||||
|
for {
|
||||||
|
runtime.EventsEmit(a.ctx, "ApiActive-"+caller.name, true)
|
||||||
|
caller.displayMu.Lock()
|
||||||
|
if caller.display {
|
||||||
|
runtime.EventsEmit(a.ctx, "PageActive", true)
|
||||||
|
}
|
||||||
|
caller.displayMu.Unlock()
|
||||||
|
|
||||||
|
resp, err := a.query(client)
|
||||||
|
if err != nil {
|
||||||
|
a.logError.Println(pkgErr("error querying api", err))
|
||||||
|
// runtime.EventsEmit(a.ctx, "ApiActive-"+caller.name, false)
|
||||||
|
a.stop(caller)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
caller.responseMu.Lock()
|
||||||
|
caller.response = resp
|
||||||
|
caller.responseMu.Unlock()
|
||||||
|
a.handleResponse(caller)
|
||||||
|
|
||||||
|
timer := time.NewTimer(caller.interval)
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
timer.Stop()
|
||||||
|
// runtime.EventsEmit(a.ctx, "ApiActive-"+caller.name, false)
|
||||||
|
a.stop(caller)
|
||||||
|
return
|
||||||
|
case <-timer.C:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Api) handleResponse(c *caller) {
|
||||||
|
if c == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.responseMu.Lock()
|
||||||
|
defer c.responseMu.Unlock()
|
||||||
|
if c.response == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.displayMu.Lock()
|
||||||
|
if c.display {
|
||||||
|
runtime.EventsEmit(a.ctx, "PageActivity", c.response)
|
||||||
|
}
|
||||||
|
c.displayMu.Unlock()
|
||||||
|
|
||||||
|
isLive := len(c.response.Livestreams) > 0
|
||||||
|
runtime.EventsEmit(a.ctx, "PageLive-"+c.name, isLive)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Api) stop(c *caller) {
|
||||||
|
if c == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
runtime.EventsEmit(a.ctx, "ApiActive-"+c.name, false)
|
||||||
|
c.displayMu.Lock()
|
||||||
|
if c.display {
|
||||||
|
c.display = false
|
||||||
|
runtime.EventsEmit(a.ctx, "PageActive", false)
|
||||||
|
}
|
||||||
|
c.displayMu.Unlock()
|
||||||
|
|
||||||
|
a.displayMu.Lock()
|
||||||
|
if a.display == c.name {
|
||||||
|
a.display = ""
|
||||||
|
}
|
||||||
|
a.displayMu.Unlock()
|
||||||
|
|
||||||
|
a.callersMu.Lock()
|
||||||
|
delete(a.callers, c.name)
|
||||||
|
a.callersMu.Unlock()
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Api) Active(name string) bool {
|
||||||
|
a.callersMu.Lock()
|
||||||
|
defer a.callersMu.Unlock()
|
||||||
|
_, active := a.callers[name]
|
||||||
|
|
||||||
|
return active
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Api) Stop(name string) error {
|
||||||
|
a.callersMu.Lock()
|
||||||
|
caller, exists := a.callers[name]
|
||||||
|
if !exists {
|
||||||
|
return pkgErr("", fmt.Errorf("caller does not exist: %s", name))
|
||||||
|
}
|
||||||
|
a.callersMu.Unlock()
|
||||||
|
|
||||||
|
caller.cancelMu.Lock()
|
||||||
|
if caller.cancel != nil {
|
||||||
|
caller.cancel()
|
||||||
|
}
|
||||||
|
caller.cancelMu.Unlock()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Api) query(client *rumblelivestreamlib.Client) (*rumblelivestreamlib.LivestreamResponse, error) {
|
||||||
|
resp, err := client.Request()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error executing client request: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return resp, nil
|
||||||
|
}
|
14
v1/internal/api/error.go
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
package api
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
const pkgName = "api"
|
||||||
|
|
||||||
|
func pkgErr(prefix string, err error) error {
|
||||||
|
pkgErr := pkgName
|
||||||
|
if prefix != "" {
|
||||||
|
pkgErr = fmt.Sprintf("%s: %s", pkgErr, prefix)
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Errorf("%s: %v", pkgErr, err)
|
||||||
|
}
|
|
@ -19,6 +19,35 @@ type Account struct {
|
||||||
ApiKey *string `json:"api_key"`
|
ApiKey *string `json:"api_key"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *Account) Id() *int64 {
|
||||||
|
return a.ID
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Account) KeyUrl() *string {
|
||||||
|
return a.ApiKey
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Account) LoggedIn() bool {
|
||||||
|
return a.Cookies != nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Account) String() *string {
|
||||||
|
if a.Username == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
s := "/user/" + *a.Username
|
||||||
|
return &s
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Account) Title() *string {
|
||||||
|
return a.Username
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Account) Type() string {
|
||||||
|
return "Account"
|
||||||
|
}
|
||||||
|
|
||||||
func (a *Account) values() []any {
|
func (a *Account) values() []any {
|
||||||
return []any{a.ID, a.UID, a.Username, a.Cookies, a.ProfileImage, a.ApiKey}
|
return []any{a.ID, a.UID, a.Username, a.Cookies, a.ProfileImage, a.ApiKey}
|
||||||
}
|
}
|
||||||
|
@ -60,8 +89,10 @@ func (sa sqlAccount) toAccount() *Account {
|
||||||
type AccountService interface {
|
type AccountService interface {
|
||||||
All() ([]Account, error)
|
All() ([]Account, error)
|
||||||
AutoMigrate() error
|
AutoMigrate() error
|
||||||
|
ByID(id int64) (*Account, error)
|
||||||
ByUsername(username string) (*Account, error)
|
ByUsername(username string) (*Account, error)
|
||||||
Create(a *Account) error
|
Create(a *Account) (int64, error)
|
||||||
|
Delete(a *Account) error
|
||||||
DestructiveReset() error
|
DestructiveReset() error
|
||||||
Update(a *Account) error
|
Update(a *Account) error
|
||||||
}
|
}
|
||||||
|
@ -138,6 +169,34 @@ func (as *accountService) createAccountTable() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (as *accountService) ByID(id int64) (*Account, error) {
|
||||||
|
err := runAccountValFuncs(
|
||||||
|
&Account{ID: &id},
|
||||||
|
accountRequireID,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, pkgErr("", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
selectQ := fmt.Sprintf(`
|
||||||
|
SELECT %s
|
||||||
|
FROM "%s"
|
||||||
|
WHERE id=?
|
||||||
|
`, accountColumns, accountTable)
|
||||||
|
|
||||||
|
var sa sqlAccount
|
||||||
|
row := as.Database.QueryRow(selectQ, id)
|
||||||
|
err = sa.scan(row)
|
||||||
|
if err != nil {
|
||||||
|
if err == sql.ErrNoRows {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
return nil, pkgErr("error executing select query", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return sa.toAccount(), nil
|
||||||
|
}
|
||||||
|
|
||||||
func (as *accountService) ByUsername(username string) (*Account, error) {
|
func (as *accountService) ByUsername(username string) (*Account, error) {
|
||||||
err := runAccountValFuncs(
|
err := runAccountValFuncs(
|
||||||
&Account{Username: &username},
|
&Account{Username: &username},
|
||||||
|
@ -166,24 +225,50 @@ func (as *accountService) ByUsername(username string) (*Account, error) {
|
||||||
return sa.toAccount(), nil
|
return sa.toAccount(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (as *accountService) Create(a *Account) error {
|
func (as *accountService) Create(a *Account) (int64, error) {
|
||||||
err := runAccountValFuncs(
|
err := runAccountValFuncs(
|
||||||
a,
|
a,
|
||||||
accountRequireUsername,
|
accountRequireUsername,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return pkgErr("invalid account", err)
|
return -1, pkgErr("invalid account", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
columns := columnsNoID(accountColumns)
|
columns := columnsNoID(accountColumns)
|
||||||
insertQ := fmt.Sprintf(`
|
insertQ := fmt.Sprintf(`
|
||||||
INSERT INTO "%s" (%s)
|
INSERT INTO "%s" (%s)
|
||||||
VALUES (%s)
|
VALUES (%s)
|
||||||
|
RETURNING id
|
||||||
`, accountTable, columns, values(columns))
|
`, accountTable, columns, values(columns))
|
||||||
|
|
||||||
_, err = as.Database.Exec(insertQ, a.valuesNoID()...)
|
// _, err = as.Database.Exec(insertQ, a.valuesNoID()...)
|
||||||
|
var id int64
|
||||||
|
row := as.Database.QueryRow(insertQ, a.valuesNoID()...)
|
||||||
|
err = row.Scan(&id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return pkgErr("error executing insert query", err)
|
return -1, pkgErr("error executing insert query", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return id, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (as *accountService) Delete(a *Account) error {
|
||||||
|
err := runAccountValFuncs(
|
||||||
|
a,
|
||||||
|
accountRequireID,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return pkgErr("invalid account", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteQ := fmt.Sprintf(`
|
||||||
|
DELETE FROM "%s"
|
||||||
|
WHERE id=?
|
||||||
|
`, accountTable)
|
||||||
|
|
||||||
|
_, err = as.Database.Exec(deleteQ, a.ID)
|
||||||
|
if err != nil {
|
||||||
|
return pkgErr("error executing delete query", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -230,7 +315,7 @@ func (as *accountService) Update(a *Account) error {
|
||||||
|
|
||||||
_, err = as.Database.Exec(updateQ, a.valuesEndID()...)
|
_, err = as.Database.Exec(updateQ, a.valuesEndID()...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return pkgErr(fmt.Sprintf("error executing update query", accountTable), err)
|
return pkgErr("error executing update query", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -3,6 +3,7 @@ package models
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -19,6 +20,35 @@ type Channel struct {
|
||||||
ApiKey *string `json:"api_key"`
|
ApiKey *string `json:"api_key"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Channel) Id() *int64 {
|
||||||
|
return c.ID
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Channel) KeyUrl() *string {
|
||||||
|
return c.ApiKey
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Channel) LoggedIn() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Channel) String() *string {
|
||||||
|
if c.Name == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
s := "/c/" + strings.ReplaceAll(*c.Name, " ", "")
|
||||||
|
return &s
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Channel) Title() *string {
|
||||||
|
return c.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Channel) Type() string {
|
||||||
|
return "Channel"
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Channel) values() []any {
|
func (c *Channel) values() []any {
|
||||||
return []any{c.ID, c.AccountID, c.CID, c.Name, c.ProfileImage, c.ApiKey}
|
return []any{c.ID, c.AccountID, c.CID, c.Name, c.ProfileImage, c.ApiKey}
|
||||||
}
|
}
|
||||||
|
@ -59,9 +89,13 @@ func (sc sqlChannel) toChannel() *Channel {
|
||||||
|
|
||||||
type ChannelService interface {
|
type ChannelService interface {
|
||||||
AutoMigrate() error
|
AutoMigrate() error
|
||||||
|
ByAccount(a *Account) ([]Channel, error)
|
||||||
|
ByID(id int64) (*Channel, error)
|
||||||
ByName(name string) (*Channel, error)
|
ByName(name string) (*Channel, error)
|
||||||
Create(c *Channel) error
|
Create(c *Channel) error
|
||||||
|
Delete(c *Channel) error
|
||||||
DestructiveReset() error
|
DestructiveReset() error
|
||||||
|
Update(c *Channel) error
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewChannelService(db *sql.DB) ChannelService {
|
func NewChannelService(db *sql.DB) ChannelService {
|
||||||
|
@ -106,6 +140,74 @@ func (cs *channelService) createChannelTable() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (cs *channelService) ByAccount(a *Account) ([]Channel, error) {
|
||||||
|
err := runAccountValFuncs(
|
||||||
|
a,
|
||||||
|
accountRequireID,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, pkgErr("", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
selectQ := fmt.Sprintf(`
|
||||||
|
SELECT %s
|
||||||
|
FROM "%s"
|
||||||
|
WHERE account_id=?
|
||||||
|
`, channelColumns, channelTable)
|
||||||
|
|
||||||
|
rows, err := cs.Database.Query(selectQ, a.ID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, pkgErr("error executing select query", err)
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
|
||||||
|
channels := []Channel{}
|
||||||
|
for rows.Next() {
|
||||||
|
sc := &sqlChannel{}
|
||||||
|
|
||||||
|
err = sc.scan(rows)
|
||||||
|
if err != nil {
|
||||||
|
return nil, pkgErr("error scanning row", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
channels = append(channels, *sc.toChannel())
|
||||||
|
}
|
||||||
|
err = rows.Err()
|
||||||
|
if err != nil && err != sql.ErrNoRows {
|
||||||
|
return nil, pkgErr("error iterating over rows", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return channels, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cs *channelService) ByID(id int64) (*Channel, error) {
|
||||||
|
err := runChannelValFuncs(
|
||||||
|
&Channel{ID: &id},
|
||||||
|
channelRequireID,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, pkgErr("", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
selectQ := fmt.Sprintf(`
|
||||||
|
SELECT %s
|
||||||
|
FROM "%s"
|
||||||
|
WHERE id=?
|
||||||
|
`, channelColumns, channelTable)
|
||||||
|
|
||||||
|
var sc sqlChannel
|
||||||
|
row := cs.Database.QueryRow(selectQ, id)
|
||||||
|
err = sc.scan(row)
|
||||||
|
if err != nil {
|
||||||
|
if err == sql.ErrNoRows {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
return nil, pkgErr("error executing select query", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return sc.toChannel(), nil
|
||||||
|
}
|
||||||
|
|
||||||
func (cs *channelService) ByName(name string) (*Channel, error) {
|
func (cs *channelService) ByName(name string) (*Channel, error) {
|
||||||
err := runChannelValFuncs(
|
err := runChannelValFuncs(
|
||||||
&Channel{Name: &name},
|
&Channel{Name: &name},
|
||||||
|
@ -160,6 +262,28 @@ func (cs *channelService) Create(c *Channel) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (cs *channelService) Delete(c *Channel) error {
|
||||||
|
err := runChannelValFuncs(
|
||||||
|
c,
|
||||||
|
channelRequireID,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return pkgErr("invalid channel", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteQ := fmt.Sprintf(`
|
||||||
|
DELETE FROM "%s"
|
||||||
|
WHERE id=?
|
||||||
|
`, channelTable)
|
||||||
|
|
||||||
|
_, err = cs.Database.Exec(deleteQ, c.ID)
|
||||||
|
if err != nil {
|
||||||
|
return pkgErr("error executing delete query", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (cs *channelService) DestructiveReset() error {
|
func (cs *channelService) DestructiveReset() error {
|
||||||
err := cs.dropChannelTable()
|
err := cs.dropChannelTable()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -182,6 +306,33 @@ func (cs *channelService) dropChannelTable() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (cs *channelService) Update(c *Channel) error {
|
||||||
|
err := runChannelValFuncs(
|
||||||
|
c,
|
||||||
|
channelRequireAccountID,
|
||||||
|
channelRequireApiKey,
|
||||||
|
channelRequireCID,
|
||||||
|
channelRequireName,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return pkgErr("invalid channel", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
columns := columnsNoID(channelColumns)
|
||||||
|
updateQ := fmt.Sprintf(`
|
||||||
|
UPDATE "%s"
|
||||||
|
SET %s
|
||||||
|
WHERE id=?
|
||||||
|
`, channelTable, set(columns))
|
||||||
|
|
||||||
|
_, err = cs.Database.Exec(updateQ, c.valuesEndID()...)
|
||||||
|
if err != nil {
|
||||||
|
return pkgErr("error executing update query", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
type channelValFunc func(*Channel) error
|
type channelValFunc func(*Channel) error
|
||||||
|
|
||||||
func runChannelValFuncs(c *Channel, fns ...channelValFunc) error {
|
func runChannelValFuncs(c *Channel, fns ...channelValFunc) error {
|
||||||
|
@ -215,6 +366,14 @@ func channelRequireApiKey(c *Channel) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func channelRequireID(c *Channel) error {
|
||||||
|
if c.ID == nil || *c.ID < 1 {
|
||||||
|
return ErrChannelInvalidID
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func channelRequireCID(c *Channel) error {
|
func channelRequireCID(c *Channel) error {
|
||||||
if c.CID == nil || *c.CID == "" {
|
if c.CID == nil || *c.CID == "" {
|
||||||
return ErrChannelInvalidCID
|
return ErrChannelInvalidCID
|
||||||
|
|
|
@ -11,6 +11,7 @@ const (
|
||||||
ErrChannelInvalidAccountID ValidatorError = "invalid channel account id"
|
ErrChannelInvalidAccountID ValidatorError = "invalid channel account id"
|
||||||
ErrChannelInvalidApiKey ValidatorError = "invalid channel API key"
|
ErrChannelInvalidApiKey ValidatorError = "invalid channel API key"
|
||||||
ErrChannelInvalidCID ValidatorError = "invalid channel CID"
|
ErrChannelInvalidCID ValidatorError = "invalid channel CID"
|
||||||
|
ErrChannelInvalidID ValidatorError = "invalid channel ID"
|
||||||
ErrChannelInvalidName ValidatorError = "invalid channel name"
|
ErrChannelInvalidName ValidatorError = "invalid channel name"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
13
v1/vendor/github.com/robertkrimen/otto/.gitignore
generated
vendored
|
@ -1,7 +1,10 @@
|
||||||
/.test
|
.test
|
||||||
/otto/otto
|
otto/otto
|
||||||
/otto/otto-*
|
otto/otto-*
|
||||||
/test/test-*.js
|
tools/tester/testdata/
|
||||||
/test/tester
|
tools/tester/tester
|
||||||
|
tools/gen-jscore/gen-jscore
|
||||||
|
tools/gen-tokens/gen-tokens
|
||||||
.idea
|
.idea
|
||||||
dist/
|
dist/
|
||||||
|
.vscode/
|
||||||
|
|
48
v1/vendor/github.com/robertkrimen/otto/.golangci.yml
generated
vendored
|
@ -4,6 +4,7 @@ run:
|
||||||
- terst
|
- terst
|
||||||
skip-files:
|
skip-files:
|
||||||
- dbg/dbg.go
|
- dbg/dbg.go
|
||||||
|
- token/token_const.go
|
||||||
|
|
||||||
linters-settings:
|
linters-settings:
|
||||||
govet:
|
govet:
|
||||||
|
@ -11,25 +12,17 @@ linters-settings:
|
||||||
goconst:
|
goconst:
|
||||||
min-len: 2
|
min-len: 2
|
||||||
min-occurrences: 4
|
min-occurrences: 4
|
||||||
|
revive:
|
||||||
|
enable-all-rules: false
|
||||||
|
rules:
|
||||||
|
- name: var-naming
|
||||||
|
disabled: true
|
||||||
|
|
||||||
linters:
|
linters:
|
||||||
enable-all: true
|
enable-all: true
|
||||||
disable:
|
disable:
|
||||||
- dupl
|
- dupl
|
||||||
- gas
|
|
||||||
- errcheck
|
|
||||||
- gofmt
|
|
||||||
- gosimple
|
|
||||||
- interfacer
|
|
||||||
- megacheck
|
|
||||||
- maligned
|
|
||||||
- structcheck
|
|
||||||
- staticcheck
|
|
||||||
- unconvert
|
|
||||||
- unparam
|
|
||||||
- varcheck
|
|
||||||
- lll
|
- lll
|
||||||
- prealloc
|
|
||||||
- gochecknoglobals
|
- gochecknoglobals
|
||||||
- gochecknoinits
|
- gochecknoinits
|
||||||
- scopelint
|
- scopelint
|
||||||
|
@ -39,35 +32,34 @@ linters:
|
||||||
- goerr113
|
- goerr113
|
||||||
- wsl
|
- wsl
|
||||||
- nlreturn
|
- nlreturn
|
||||||
- tagliatelle
|
|
||||||
- gomnd
|
- gomnd
|
||||||
- paralleltest
|
- paralleltest
|
||||||
- wrapcheck
|
- wrapcheck
|
||||||
- testpackage
|
- testpackage
|
||||||
- golint
|
|
||||||
- gofumpt
|
|
||||||
- forbidigo
|
|
||||||
- gocognit
|
- gocognit
|
||||||
- gocritic
|
|
||||||
- godot
|
|
||||||
- nakedret
|
|
||||||
- nestif
|
- nestif
|
||||||
- revive
|
|
||||||
- errorlint
|
|
||||||
- exhaustive
|
- exhaustive
|
||||||
- forcetypeassert
|
- forcetypeassert
|
||||||
- ifshort
|
|
||||||
- stylecheck
|
|
||||||
- gocyclo
|
- gocyclo
|
||||||
- misspell
|
|
||||||
- cyclop
|
- cyclop
|
||||||
- varnamelen
|
- varnamelen
|
||||||
- nonamedreturns
|
|
||||||
- maintidx
|
- maintidx
|
||||||
- ireturn
|
- ireturn
|
||||||
- exhaustruct
|
- exhaustruct
|
||||||
- nosnakecase
|
- nosnakecase
|
||||||
- deadcode
|
|
||||||
- dupword
|
- dupword
|
||||||
- gci
|
- structcheck
|
||||||
|
- deadcode
|
||||||
|
- golint
|
||||||
|
- varcheck
|
||||||
|
- ifshort
|
||||||
|
- interfacer
|
||||||
|
- maligned
|
||||||
|
# Just causes noise
|
||||||
|
- depguard
|
||||||
|
|
||||||
|
issues:
|
||||||
|
exclude-use-default: false
|
||||||
|
max-same-issues: 0
|
||||||
|
exclude:
|
||||||
|
- Deferring unsafe method "Close" on type "io\.ReadCloser"
|
||||||
|
|
63
v1/vendor/github.com/robertkrimen/otto/Makefile
generated
vendored
|
@ -1,63 +0,0 @@
|
||||||
.PHONY: test test-race test-release release release-check test-262
|
|
||||||
.PHONY: parser
|
|
||||||
.PHONY: otto assets underscore
|
|
||||||
|
|
||||||
TESTS := \
|
|
||||||
~
|
|
||||||
|
|
||||||
TEST := -v --run
|
|
||||||
TEST := -v
|
|
||||||
TEST := -v --run Test\($(subst $(eval) ,\|,$(TESTS))\)
|
|
||||||
TEST := .
|
|
||||||
|
|
||||||
test: parser inline.go
|
|
||||||
go test -i
|
|
||||||
go test $(TEST)
|
|
||||||
@echo PASS
|
|
||||||
|
|
||||||
parser:
|
|
||||||
$(MAKE) -C parser
|
|
||||||
|
|
||||||
inline.go: inline.pl
|
|
||||||
./$< > $@
|
|
||||||
|
|
||||||
#################
|
|
||||||
# release, test #
|
|
||||||
#################
|
|
||||||
|
|
||||||
release: test-race test-release
|
|
||||||
for package in . parser token ast file underscore registry; do (cd $$package && godocdown --signature > README.markdown); done
|
|
||||||
@echo \*\*\* make release-check
|
|
||||||
@echo PASS
|
|
||||||
|
|
||||||
release-check: .test
|
|
||||||
$(MAKE) -C test build test
|
|
||||||
$(MAKE) -C .test/test262 build test
|
|
||||||
@echo PASS
|
|
||||||
|
|
||||||
test-262: .test
|
|
||||||
$(MAKE) -C .test/test262 build test
|
|
||||||
@echo PASS
|
|
||||||
|
|
||||||
test-release:
|
|
||||||
go test -i
|
|
||||||
go test
|
|
||||||
|
|
||||||
test-race:
|
|
||||||
go test -race -i
|
|
||||||
go test -race
|
|
||||||
|
|
||||||
#################################
|
|
||||||
# otto, assets, underscore, ... #
|
|
||||||
#################################
|
|
||||||
|
|
||||||
otto:
|
|
||||||
$(MAKE) -C otto
|
|
||||||
|
|
||||||
assets:
|
|
||||||
mkdir -p .assets
|
|
||||||
for file in underscore/test/*.js; do tr "\`" "_" < $$file > .assets/`basename $$file`; done
|
|
||||||
|
|
||||||
underscore:
|
|
||||||
$(MAKE) -C $@
|
|
||||||
|
|
1068
v1/vendor/github.com/robertkrimen/otto/ast/README.markdown
generated
vendored
73
v1/vendor/github.com/robertkrimen/otto/ast/comments.go
generated
vendored
|
@ -6,32 +6,44 @@ import (
|
||||||
"github.com/robertkrimen/otto/file"
|
"github.com/robertkrimen/otto/file"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CommentPosition determines where the comment is in a given context
|
// CommentPosition determines where the comment is in a given context.
|
||||||
type CommentPosition int
|
type CommentPosition int
|
||||||
|
|
||||||
|
// Available comment positions.
|
||||||
const (
|
const (
|
||||||
_ CommentPosition = iota
|
_ CommentPosition = iota
|
||||||
LEADING // Before the pertinent expression
|
// LEADING is before the pertinent expression.
|
||||||
TRAILING // After the pertinent expression
|
LEADING
|
||||||
KEY // Before a key in an object
|
// TRAILING is after the pertinent expression.
|
||||||
COLON // After a colon in a field declaration
|
TRAILING
|
||||||
FINAL // Final comments in a block, not belonging to a specific expression or the comment after a trailing , in an array or object literal
|
// KEY is before a key in an object.
|
||||||
IF // After an if keyword
|
KEY
|
||||||
WHILE // After a while keyword
|
// COLON is after a colon in a field declaration.
|
||||||
DO // After do keyword
|
COLON
|
||||||
FOR // After a for keyword
|
// FINAL is the final comments in a block, not belonging to a specific expression or the comment after a trailing , in an array or object literal.
|
||||||
WITH // After a with keyword
|
FINAL
|
||||||
|
// IF is after an if keyword.
|
||||||
|
IF
|
||||||
|
// WHILE is after a while keyword.
|
||||||
|
WHILE
|
||||||
|
// DO is after do keyword.
|
||||||
|
DO
|
||||||
|
// FOR is after a for keyword.
|
||||||
|
FOR
|
||||||
|
// WITH is after a with keyword.
|
||||||
|
WITH
|
||||||
|
// TBD is unknown.
|
||||||
TBD
|
TBD
|
||||||
)
|
)
|
||||||
|
|
||||||
// Comment contains the data of the comment
|
// Comment contains the data of the comment.
|
||||||
type Comment struct {
|
type Comment struct {
|
||||||
Begin file.Idx
|
Begin file.Idx
|
||||||
Text string
|
Text string
|
||||||
Position CommentPosition
|
Position CommentPosition
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewComment creates a new comment
|
// NewComment creates a new comment.
|
||||||
func NewComment(text string, idx file.Idx) *Comment {
|
func NewComment(text string, idx file.Idx) *Comment {
|
||||||
comment := &Comment{
|
comment := &Comment{
|
||||||
Begin: idx,
|
Begin: idx,
|
||||||
|
@ -42,7 +54,7 @@ func NewComment(text string, idx file.Idx) *Comment {
|
||||||
return comment
|
return comment
|
||||||
}
|
}
|
||||||
|
|
||||||
// String returns a stringified version of the position
|
// String returns a stringified version of the position.
|
||||||
func (cp CommentPosition) String() string {
|
func (cp CommentPosition) String() string {
|
||||||
switch cp {
|
switch cp {
|
||||||
case LEADING:
|
case LEADING:
|
||||||
|
@ -70,23 +82,23 @@ func (cp CommentPosition) String() string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// String returns a stringified version of the comment
|
// String returns a stringified version of the comment.
|
||||||
func (c Comment) String() string {
|
func (c Comment) String() string {
|
||||||
return fmt.Sprintf("Comment: %v", c.Text)
|
return fmt.Sprintf("Comment: %v", c.Text)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Comments defines the current view of comments from the parser
|
// Comments defines the current view of comments from the parser.
|
||||||
type Comments struct {
|
type Comments struct {
|
||||||
// CommentMap is a reference to the parser comment map
|
// CommentMap is a reference to the parser comment map
|
||||||
CommentMap CommentMap
|
CommentMap CommentMap
|
||||||
// Comments lists the comments scanned, not linked to a node yet
|
// Comments lists the comments scanned, not linked to a node yet
|
||||||
Comments []*Comment
|
Comments []*Comment
|
||||||
// future lists the comments after a line break during a sequence of comments
|
|
||||||
future []*Comment
|
|
||||||
// Current is node for which comments are linked to
|
// Current is node for which comments are linked to
|
||||||
Current Expression
|
Current Expression
|
||||||
|
|
||||||
// wasLineBreak determines if a line break occured while scanning for comments
|
// future lists the comments after a line break during a sequence of comments
|
||||||
|
future []*Comment
|
||||||
|
// wasLineBreak determines if a line break occurred while scanning for comments
|
||||||
wasLineBreak bool
|
wasLineBreak bool
|
||||||
// primary determines whether or not processing a primary expression
|
// primary determines whether or not processing a primary expression
|
||||||
primary bool
|
primary bool
|
||||||
|
@ -94,6 +106,7 @@ type Comments struct {
|
||||||
afterBlock bool
|
afterBlock bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewComments returns a new Comments.
|
||||||
func NewComments() *Comments {
|
func NewComments() *Comments {
|
||||||
comments := &Comments{
|
comments := &Comments{
|
||||||
CommentMap: CommentMap{},
|
CommentMap: CommentMap{},
|
||||||
|
@ -107,7 +120,7 @@ func (c *Comments) String() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// FetchAll returns all the currently scanned comments,
|
// FetchAll returns all the currently scanned comments,
|
||||||
// including those from the next line
|
// including those from the next line.
|
||||||
func (c *Comments) FetchAll() []*Comment {
|
func (c *Comments) FetchAll() []*Comment {
|
||||||
defer func() {
|
defer func() {
|
||||||
c.Comments = nil
|
c.Comments = nil
|
||||||
|
@ -117,7 +130,7 @@ func (c *Comments) FetchAll() []*Comment {
|
||||||
return append(c.Comments, c.future...)
|
return append(c.Comments, c.future...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch returns all the currently scanned comments
|
// Fetch returns all the currently scanned comments.
|
||||||
func (c *Comments) Fetch() []*Comment {
|
func (c *Comments) Fetch() []*Comment {
|
||||||
defer func() {
|
defer func() {
|
||||||
c.Comments = nil
|
c.Comments = nil
|
||||||
|
@ -126,12 +139,12 @@ func (c *Comments) Fetch() []*Comment {
|
||||||
return c.Comments
|
return c.Comments
|
||||||
}
|
}
|
||||||
|
|
||||||
// ResetLineBreak marks the beginning of a new statement
|
// ResetLineBreak marks the beginning of a new statement.
|
||||||
func (c *Comments) ResetLineBreak() {
|
func (c *Comments) ResetLineBreak() {
|
||||||
c.wasLineBreak = false
|
c.wasLineBreak = false
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarkPrimary will mark the context as processing a primary expression
|
// MarkPrimary will mark the context as processing a primary expression.
|
||||||
func (c *Comments) MarkPrimary() {
|
func (c *Comments) MarkPrimary() {
|
||||||
c.primary = true
|
c.primary = true
|
||||||
c.wasLineBreak = false
|
c.wasLineBreak = false
|
||||||
|
@ -205,7 +218,7 @@ func (c *Comments) SetExpression(node Expression) {
|
||||||
c.applyComments(node, previous, TRAILING)
|
c.applyComments(node, previous, TRAILING)
|
||||||
}
|
}
|
||||||
|
|
||||||
// PostProcessNode applies all found comments to the given node
|
// PostProcessNode applies all found comments to the given node.
|
||||||
func (c *Comments) PostProcessNode(node Node) {
|
func (c *Comments) PostProcessNode(node Node) {
|
||||||
c.applyComments(node, nil, TRAILING)
|
c.applyComments(node, nil, TRAILING)
|
||||||
}
|
}
|
||||||
|
@ -228,15 +241,15 @@ func (c *Comments) applyComments(node, previous Node, position CommentPosition)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// AtLineBreak will mark a line break
|
// AtLineBreak will mark a line break.
|
||||||
func (c *Comments) AtLineBreak() {
|
func (c *Comments) AtLineBreak() {
|
||||||
c.wasLineBreak = true
|
c.wasLineBreak = true
|
||||||
}
|
}
|
||||||
|
|
||||||
// CommentMap is the data structure where all found comments are stored
|
// CommentMap is the data structure where all found comments are stored.
|
||||||
type CommentMap map[Node][]*Comment
|
type CommentMap map[Node][]*Comment
|
||||||
|
|
||||||
// AddComment adds a single comment to the map
|
// AddComment adds a single comment to the map.
|
||||||
func (cm CommentMap) AddComment(node Node, comment *Comment) {
|
func (cm CommentMap) AddComment(node Node, comment *Comment) {
|
||||||
list := cm[node]
|
list := cm[node]
|
||||||
list = append(list, comment)
|
list = append(list, comment)
|
||||||
|
@ -244,7 +257,7 @@ func (cm CommentMap) AddComment(node Node, comment *Comment) {
|
||||||
cm[node] = list
|
cm[node] = list
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddComments adds a slice of comments, given a node and an updated position
|
// AddComments adds a slice of comments, given a node and an updated position.
|
||||||
func (cm CommentMap) AddComments(node Node, comments []*Comment, position CommentPosition) {
|
func (cm CommentMap) AddComments(node Node, comments []*Comment, position CommentPosition) {
|
||||||
for _, comment := range comments {
|
for _, comment := range comments {
|
||||||
if comment.Position == TBD {
|
if comment.Position == TBD {
|
||||||
|
@ -254,7 +267,7 @@ func (cm CommentMap) AddComments(node Node, comments []*Comment, position Commen
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Size returns the size of the map
|
// Size returns the size of the map.
|
||||||
func (cm CommentMap) Size() int {
|
func (cm CommentMap) Size() int {
|
||||||
size := 0
|
size := 0
|
||||||
for _, comments := range cm {
|
for _, comments := range cm {
|
||||||
|
@ -264,7 +277,7 @@ func (cm CommentMap) Size() int {
|
||||||
return size
|
return size
|
||||||
}
|
}
|
||||||
|
|
||||||
// MoveComments moves comments with a given position from a node to another
|
// MoveComments moves comments with a given position from a node to another.
|
||||||
func (cm CommentMap) MoveComments(from, to Node, position CommentPosition) {
|
func (cm CommentMap) MoveComments(from, to Node, position CommentPosition) {
|
||||||
for i, c := range cm[from] {
|
for i, c := range cm[from] {
|
||||||
if c.Position == position {
|
if c.Position == position {
|
||||||
|
|
963
v1/vendor/github.com/robertkrimen/otto/ast/node.go
generated
vendored
1
v1/vendor/github.com/robertkrimen/otto/ast/walk.go
generated
vendored
|
@ -38,6 +38,7 @@ func Walk(v Visitor, n Node) {
|
||||||
Walk(v, n.Right)
|
Walk(v, n.Right)
|
||||||
}
|
}
|
||||||
case *BadExpression:
|
case *BadExpression:
|
||||||
|
case *BadStatement:
|
||||||
case *BinaryExpression:
|
case *BinaryExpression:
|
||||||
if n != nil {
|
if n != nil {
|
||||||
Walk(v, n.Left)
|
Walk(v, n.Left)
|
||||||
|
|
118
v1/vendor/github.com/robertkrimen/otto/builtin.go
generated
vendored
|
@ -2,6 +2,7 @@ package otto
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
"errors"
|
||||||
"math"
|
"math"
|
||||||
"net/url"
|
"net/url"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
@ -11,34 +12,34 @@ import (
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Global
|
// Global.
|
||||||
func builtinGlobal_eval(call FunctionCall) Value {
|
func builtinGlobalEval(call FunctionCall) Value {
|
||||||
src := call.Argument(0)
|
src := call.Argument(0)
|
||||||
if !src.IsString() {
|
if !src.IsString() {
|
||||||
return src
|
return src
|
||||||
}
|
}
|
||||||
runtime := call.runtime
|
rt := call.runtime
|
||||||
program := runtime.cmpl_parseOrThrow(src.string(), nil)
|
program := rt.cmplParseOrThrow(src.string(), nil)
|
||||||
if !call.eval {
|
if !call.eval {
|
||||||
// Not a direct call to eval, so we enter the global ExecutionContext
|
// Not a direct call to eval, so we enter the global ExecutionContext
|
||||||
runtime.enterGlobalScope()
|
rt.enterGlobalScope()
|
||||||
defer runtime.leaveScope()
|
defer rt.leaveScope()
|
||||||
}
|
}
|
||||||
returnValue := runtime.cmpl_evaluate_nodeProgram(program, true)
|
returnValue := rt.cmplEvaluateNodeProgram(program, true)
|
||||||
if returnValue.isEmpty() {
|
if returnValue.isEmpty() {
|
||||||
return Value{}
|
return Value{}
|
||||||
}
|
}
|
||||||
return returnValue
|
return returnValue
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinGlobal_isNaN(call FunctionCall) Value {
|
func builtinGlobalIsNaN(call FunctionCall) Value {
|
||||||
value := call.Argument(0).float64()
|
value := call.Argument(0).float64()
|
||||||
return toValue_bool(math.IsNaN(value))
|
return boolValue(math.IsNaN(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinGlobal_isFinite(call FunctionCall) Value {
|
func builtinGlobalIsFinite(call FunctionCall) Value {
|
||||||
value := call.Argument(0).float64()
|
value := call.Argument(0).float64()
|
||||||
return toValue_bool(!math.IsNaN(value) && !math.IsInf(value, 0))
|
return boolValue(!math.IsNaN(value) && !math.IsInf(value, 0))
|
||||||
}
|
}
|
||||||
|
|
||||||
func digitValue(chr rune) int {
|
func digitValue(chr rune) int {
|
||||||
|
@ -53,8 +54,8 @@ func digitValue(chr rune) int {
|
||||||
return 36 // Larger than any legal digit value
|
return 36 // Larger than any legal digit value
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinGlobal_parseInt(call FunctionCall) Value {
|
func builtinGlobalParseInt(call FunctionCall) Value {
|
||||||
input := strings.Trim(call.Argument(0).string(), builtinString_trim_whitespace)
|
input := strings.Trim(call.Argument(0).string(), builtinStringTrimWhitespace)
|
||||||
if len(input) == 0 {
|
if len(input) == 0 {
|
||||||
return NaNValue()
|
return NaNValue()
|
||||||
}
|
}
|
||||||
|
@ -106,7 +107,7 @@ func builtinGlobal_parseInt(call FunctionCall) Value {
|
||||||
|
|
||||||
value, err := strconv.ParseInt(input, radix, 64)
|
value, err := strconv.ParseInt(input, radix, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err.(*strconv.NumError).Err == strconv.ErrRange {
|
if errors.Is(err, strconv.ErrRange) {
|
||||||
base := float64(base)
|
base := float64(base)
|
||||||
// Could just be a very large number (e.g. 0x8000000000000000)
|
// Could just be a very large number (e.g. 0x8000000000000000)
|
||||||
var value float64
|
var value float64
|
||||||
|
@ -120,7 +121,7 @@ func builtinGlobal_parseInt(call FunctionCall) Value {
|
||||||
if negative {
|
if negative {
|
||||||
value *= -1
|
value *= -1
|
||||||
}
|
}
|
||||||
return toValue_float64(value)
|
return float64Value(value)
|
||||||
}
|
}
|
||||||
return NaNValue()
|
return NaNValue()
|
||||||
}
|
}
|
||||||
|
@ -128,24 +129,26 @@ func builtinGlobal_parseInt(call FunctionCall) Value {
|
||||||
value *= -1
|
value *= -1
|
||||||
}
|
}
|
||||||
|
|
||||||
return toValue_int64(value)
|
return int64Value(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
var parseFloat_matchBadSpecial = regexp.MustCompile(`[\+\-]?(?:[Ii]nf$|infinity)`)
|
var (
|
||||||
var parseFloat_matchValid = regexp.MustCompile(`[0-9eE\+\-\.]|Infinity`)
|
parseFloatMatchBadSpecial = regexp.MustCompile(`[\+\-]?(?:[Ii]nf$|infinity)`)
|
||||||
|
parseFloatMatchValid = regexp.MustCompile(`[0-9eE\+\-\.]|Infinity`)
|
||||||
|
)
|
||||||
|
|
||||||
func builtinGlobal_parseFloat(call FunctionCall) Value {
|
func builtinGlobalParseFloat(call FunctionCall) Value {
|
||||||
// Caveat emptor: This implementation does NOT match the specification
|
// Caveat emptor: This implementation does NOT match the specification
|
||||||
input := strings.Trim(call.Argument(0).string(), builtinString_trim_whitespace)
|
input := strings.Trim(call.Argument(0).string(), builtinStringTrimWhitespace)
|
||||||
|
|
||||||
if parseFloat_matchBadSpecial.MatchString(input) {
|
if parseFloatMatchBadSpecial.MatchString(input) {
|
||||||
return NaNValue()
|
return NaNValue()
|
||||||
}
|
}
|
||||||
value, err := strconv.ParseFloat(input, 64)
|
value, err := strconv.ParseFloat(input, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
for end := len(input); end > 0; end-- {
|
for end := len(input); end > 0; end-- {
|
||||||
input := input[0:end]
|
input := input[0:end]
|
||||||
if !parseFloat_matchValid.MatchString(input) {
|
if !parseFloatMatchValid.MatchString(input) {
|
||||||
return NaNValue()
|
return NaNValue()
|
||||||
}
|
}
|
||||||
value, err = strconv.ParseFloat(input, 64)
|
value, err = strconv.ParseFloat(input, 64)
|
||||||
|
@ -157,12 +160,12 @@ func builtinGlobal_parseFloat(call FunctionCall) Value {
|
||||||
return NaNValue()
|
return NaNValue()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return toValue_float64(value)
|
return float64Value(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// encodeURI/decodeURI
|
// encodeURI/decodeURI
|
||||||
|
|
||||||
func _builtinGlobal_encodeURI(call FunctionCall, escape *regexp.Regexp) Value {
|
func encodeDecodeURI(call FunctionCall, escape *regexp.Regexp) Value {
|
||||||
value := call.Argument(0)
|
value := call.Argument(0)
|
||||||
var input []uint16
|
var input []uint16
|
||||||
switch vl := value.value.(type) {
|
switch vl := value.value.(type) {
|
||||||
|
@ -172,7 +175,7 @@ func _builtinGlobal_encodeURI(call FunctionCall, escape *regexp.Regexp) Value {
|
||||||
input = utf16.Encode([]rune(value.string()))
|
input = utf16.Encode([]rune(value.string()))
|
||||||
}
|
}
|
||||||
if len(input) == 0 {
|
if len(input) == 0 {
|
||||||
return toValue_string("")
|
return stringValue("")
|
||||||
}
|
}
|
||||||
output := []byte{}
|
output := []byte{}
|
||||||
length := len(input)
|
length := len(input)
|
||||||
|
@ -184,7 +187,7 @@ func _builtinGlobal_encodeURI(call FunctionCall, escape *regexp.Regexp) Value {
|
||||||
panic(call.runtime.panicURIError("URI malformed"))
|
panic(call.runtime.panicURIError("URI malformed"))
|
||||||
}
|
}
|
||||||
if value >= 0xD800 && value <= 0xDBFF {
|
if value >= 0xD800 && value <= 0xDBFF {
|
||||||
index += 1
|
index++
|
||||||
if index >= length {
|
if index >= length {
|
||||||
panic(call.runtime.panicURIError("URI malformed"))
|
panic(call.runtime.panicURIError("URI malformed"))
|
||||||
}
|
}
|
||||||
|
@ -195,43 +198,42 @@ func _builtinGlobal_encodeURI(call FunctionCall, escape *regexp.Regexp) Value {
|
||||||
}
|
}
|
||||||
decode = []rune{((rune(value) - 0xD800) * 0x400) + (rune(value1) - 0xDC00) + 0x10000}
|
decode = []rune{((rune(value) - 0xD800) * 0x400) + (rune(value1) - 0xDC00) + 0x10000}
|
||||||
}
|
}
|
||||||
index += 1
|
index++
|
||||||
size := utf8.EncodeRune(encode, decode[0])
|
size := utf8.EncodeRune(encode, decode[0])
|
||||||
encode := encode[0:size]
|
encode := encode[0:size]
|
||||||
output = append(output, encode...)
|
output = append(output, encode...)
|
||||||
}
|
}
|
||||||
{
|
|
||||||
value := escape.ReplaceAllFunc(output, func(target []byte) []byte {
|
bytes := escape.ReplaceAllFunc(output, func(target []byte) []byte {
|
||||||
// Probably a better way of doing this
|
// Probably a better way of doing this
|
||||||
if target[0] == ' ' {
|
if target[0] == ' ' {
|
||||||
return []byte("%20")
|
return []byte("%20")
|
||||||
}
|
}
|
||||||
return []byte(url.QueryEscape(string(target)))
|
return []byte(url.QueryEscape(string(target)))
|
||||||
})
|
})
|
||||||
return toValue_string(string(value))
|
return stringValue(string(bytes))
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var encodeURI_Regexp = regexp.MustCompile(`([^~!@#$&*()=:/,;?+'])`)
|
var encodeURIRegexp = regexp.MustCompile(`([^~!@#$&*()=:/,;?+'])`)
|
||||||
|
|
||||||
func builtinGlobal_encodeURI(call FunctionCall) Value {
|
func builtinGlobalEncodeURI(call FunctionCall) Value {
|
||||||
return _builtinGlobal_encodeURI(call, encodeURI_Regexp)
|
return encodeDecodeURI(call, encodeURIRegexp)
|
||||||
}
|
}
|
||||||
|
|
||||||
var encodeURIComponent_Regexp = regexp.MustCompile(`([^~!*()'])`)
|
var encodeURIComponentRegexp = regexp.MustCompile(`([^~!*()'])`)
|
||||||
|
|
||||||
func builtinGlobal_encodeURIComponent(call FunctionCall) Value {
|
func builtinGlobalEncodeURIComponent(call FunctionCall) Value {
|
||||||
return _builtinGlobal_encodeURI(call, encodeURIComponent_Regexp)
|
return encodeDecodeURI(call, encodeURIComponentRegexp)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3B/2F/3F/3A/40/26/3D/2B/24/2C/23
|
// 3B/2F/3F/3A/40/26/3D/2B/24/2C/23.
|
||||||
var decodeURI_guard = regexp.MustCompile(`(?i)(?:%)(3B|2F|3F|3A|40|26|3D|2B|24|2C|23)`)
|
var decodeURIGuard = regexp.MustCompile(`(?i)(?:%)(3B|2F|3F|3A|40|26|3D|2B|24|2C|23)`)
|
||||||
|
|
||||||
func _decodeURI(input string, reserve bool) (string, bool) {
|
func decodeURI(input string, reserve bool) (string, bool) {
|
||||||
if reserve {
|
if reserve {
|
||||||
input = decodeURI_guard.ReplaceAllString(input, "%25$1")
|
input = decodeURIGuard.ReplaceAllString(input, "%25$1")
|
||||||
}
|
}
|
||||||
input = strings.Replace(input, "+", "%2B", -1) // Ugly hack to make QueryUnescape work with our use case
|
input = strings.ReplaceAll(input, "+", "%2B") // Ugly hack to make QueryUnescape work with our use case
|
||||||
output, err := url.QueryUnescape(input)
|
output, err := url.QueryUnescape(input)
|
||||||
if err != nil || !utf8.ValidString(output) {
|
if err != nil || !utf8.ValidString(output) {
|
||||||
return "", true
|
return "", true
|
||||||
|
@ -239,25 +241,25 @@ func _decodeURI(input string, reserve bool) (string, bool) {
|
||||||
return output, false
|
return output, false
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinGlobal_decodeURI(call FunctionCall) Value {
|
func builtinGlobalDecodeURI(call FunctionCall) Value {
|
||||||
output, err := _decodeURI(call.Argument(0).string(), true)
|
output, err := decodeURI(call.Argument(0).string(), true)
|
||||||
if err {
|
if err {
|
||||||
panic(call.runtime.panicURIError("URI malformed"))
|
panic(call.runtime.panicURIError("URI malformed"))
|
||||||
}
|
}
|
||||||
return toValue_string(output)
|
return stringValue(output)
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinGlobal_decodeURIComponent(call FunctionCall) Value {
|
func builtinGlobalDecodeURIComponent(call FunctionCall) Value {
|
||||||
output, err := _decodeURI(call.Argument(0).string(), false)
|
output, err := decodeURI(call.Argument(0).string(), false)
|
||||||
if err {
|
if err {
|
||||||
panic(call.runtime.panicURIError("URI malformed"))
|
panic(call.runtime.panicURIError("URI malformed"))
|
||||||
}
|
}
|
||||||
return toValue_string(output)
|
return stringValue(output)
|
||||||
}
|
}
|
||||||
|
|
||||||
// escape/unescape
|
// escape/unescape
|
||||||
|
|
||||||
func builtin_shouldEscape(chr byte) bool {
|
func builtinShouldEscape(chr byte) bool {
|
||||||
if 'A' <= chr && chr <= 'Z' || 'a' <= chr && chr <= 'z' || '0' <= chr && chr <= '9' {
|
if 'A' <= chr && chr <= 'Z' || 'a' <= chr && chr <= 'z' || '0' <= chr && chr <= '9' {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -266,11 +268,11 @@ func builtin_shouldEscape(chr byte) bool {
|
||||||
|
|
||||||
const escapeBase16 = "0123456789ABCDEF"
|
const escapeBase16 = "0123456789ABCDEF"
|
||||||
|
|
||||||
func builtin_escape(input string) string {
|
func builtinEscape(input string) string {
|
||||||
output := make([]byte, 0, len(input))
|
output := make([]byte, 0, len(input))
|
||||||
length := len(input)
|
length := len(input)
|
||||||
for index := 0; index < length; {
|
for index := 0; index < length; {
|
||||||
if builtin_shouldEscape(input[index]) {
|
if builtinShouldEscape(input[index]) {
|
||||||
chr, width := utf8.DecodeRuneInString(input[index:])
|
chr, width := utf8.DecodeRuneInString(input[index:])
|
||||||
chr16 := utf16.Encode([]rune{chr})[0]
|
chr16 := utf16.Encode([]rune{chr})[0]
|
||||||
if 256 > chr16 {
|
if 256 > chr16 {
|
||||||
|
@ -289,13 +291,13 @@ func builtin_escape(input string) string {
|
||||||
index += width
|
index += width
|
||||||
} else {
|
} else {
|
||||||
output = append(output, input[index])
|
output = append(output, input[index])
|
||||||
index += 1
|
index++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return string(output)
|
return string(output)
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtin_unescape(input string) string {
|
func builtinUnescape(input string) string {
|
||||||
output := make([]rune, 0, len(input))
|
output := make([]rune, 0, len(input))
|
||||||
length := len(input)
|
length := len(input)
|
||||||
for index := 0; index < length; {
|
for index := 0; index < length; {
|
||||||
|
@ -322,15 +324,15 @@ func builtin_unescape(input string) string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
output = append(output, rune(input[index]))
|
output = append(output, rune(input[index]))
|
||||||
index += 1
|
index++
|
||||||
}
|
}
|
||||||
return string(output)
|
return string(output)
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinGlobal_escape(call FunctionCall) Value {
|
func builtinGlobalEscape(call FunctionCall) Value {
|
||||||
return toValue_string(builtin_escape(call.Argument(0).string()))
|
return stringValue(builtinEscape(call.Argument(0).string()))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinGlobal_unescape(call FunctionCall) Value {
|
func builtinGlobalUnescape(call FunctionCall) Value {
|
||||||
return toValue_string(builtin_unescape(call.Argument(0).string()))
|
return stringValue(builtinUnescape(call.Argument(0).string()))
|
||||||
}
|
}
|
||||||
|
|
248
v1/vendor/github.com/robertkrimen/otto/builtin_array.go
generated
vendored
|
@ -8,92 +8,93 @@ import (
|
||||||
// Array
|
// Array
|
||||||
|
|
||||||
func builtinArray(call FunctionCall) Value {
|
func builtinArray(call FunctionCall) Value {
|
||||||
return toValue_object(builtinNewArrayNative(call.runtime, call.ArgumentList))
|
return objectValue(builtinNewArrayNative(call.runtime, call.ArgumentList))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinNewArray(self *_object, argumentList []Value) Value {
|
func builtinNewArray(obj *object, argumentList []Value) Value {
|
||||||
return toValue_object(builtinNewArrayNative(self.runtime, argumentList))
|
return objectValue(builtinNewArrayNative(obj.runtime, argumentList))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinNewArrayNative(runtime *_runtime, argumentList []Value) *_object {
|
func builtinNewArrayNative(rt *runtime, argumentList []Value) *object {
|
||||||
if len(argumentList) == 1 {
|
if len(argumentList) == 1 {
|
||||||
firstArgument := argumentList[0]
|
firstArgument := argumentList[0]
|
||||||
if firstArgument.IsNumber() {
|
if firstArgument.IsNumber() {
|
||||||
return runtime.newArray(arrayUint32(runtime, firstArgument))
|
return rt.newArray(arrayUint32(rt, firstArgument))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return runtime.newArrayOf(argumentList)
|
return rt.newArrayOf(argumentList)
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinArray_toString(call FunctionCall) Value {
|
func builtinArrayToString(call FunctionCall) Value {
|
||||||
thisObject := call.thisObject()
|
thisObject := call.thisObject()
|
||||||
join := thisObject.get("join")
|
join := thisObject.get("join")
|
||||||
if join.isCallable() {
|
if join.isCallable() {
|
||||||
join := join._object()
|
join := join.object()
|
||||||
return join.call(call.This, call.ArgumentList, false, nativeFrame)
|
return join.call(call.This, call.ArgumentList, false, nativeFrame)
|
||||||
}
|
}
|
||||||
return builtinObject_toString(call)
|
return builtinObjectToString(call)
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinArray_toLocaleString(call FunctionCall) Value {
|
func builtinArrayToLocaleString(call FunctionCall) Value {
|
||||||
separator := ","
|
separator := ","
|
||||||
thisObject := call.thisObject()
|
thisObject := call.thisObject()
|
||||||
length := int64(toUint32(thisObject.get(propertyLength)))
|
length := int64(toUint32(thisObject.get(propertyLength)))
|
||||||
if length == 0 {
|
if length == 0 {
|
||||||
return toValue_string("")
|
return stringValue("")
|
||||||
}
|
}
|
||||||
stringList := make([]string, 0, length)
|
stringList := make([]string, 0, length)
|
||||||
for index := int64(0); index < length; index += 1 {
|
for index := int64(0); index < length; index++ {
|
||||||
value := thisObject.get(arrayIndexToString(index))
|
value := thisObject.get(arrayIndexToString(index))
|
||||||
stringValue := ""
|
stringValue := ""
|
||||||
switch value.kind {
|
switch value.kind {
|
||||||
case valueEmpty, valueUndefined, valueNull:
|
case valueEmpty, valueUndefined, valueNull:
|
||||||
default:
|
default:
|
||||||
object := call.runtime.toObject(value)
|
obj := call.runtime.toObject(value)
|
||||||
toLocaleString := object.get("toLocaleString")
|
toLocaleString := obj.get("toLocaleString")
|
||||||
if !toLocaleString.isCallable() {
|
if !toLocaleString.isCallable() {
|
||||||
panic(call.runtime.panicTypeError())
|
panic(call.runtime.panicTypeError("Array.toLocaleString index[%d] %q is not callable", index, toLocaleString))
|
||||||
}
|
}
|
||||||
stringValue = toLocaleString.call(call.runtime, toValue_object(object)).string()
|
stringValue = toLocaleString.call(call.runtime, objectValue(obj)).string()
|
||||||
}
|
}
|
||||||
stringList = append(stringList, stringValue)
|
stringList = append(stringList, stringValue)
|
||||||
}
|
}
|
||||||
return toValue_string(strings.Join(stringList, separator))
|
return stringValue(strings.Join(stringList, separator))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinArray_concat(call FunctionCall) Value {
|
func builtinArrayConcat(call FunctionCall) Value {
|
||||||
thisObject := call.thisObject()
|
thisObject := call.thisObject()
|
||||||
valueArray := []Value{}
|
valueArray := []Value{}
|
||||||
source := append([]Value{toValue_object(thisObject)}, call.ArgumentList...)
|
source := append([]Value{objectValue(thisObject)}, call.ArgumentList...)
|
||||||
for _, item := range source {
|
for _, item := range source {
|
||||||
switch item.kind {
|
switch item.kind {
|
||||||
case valueObject:
|
case valueObject:
|
||||||
object := item._object()
|
obj := item.object()
|
||||||
if isArray(object) {
|
if isArray(obj) {
|
||||||
length := object.get(propertyLength).number().int64
|
length := obj.get(propertyLength).number().int64
|
||||||
for index := int64(0); index < length; index += 1 {
|
for index := int64(0); index < length; index++ {
|
||||||
name := strconv.FormatInt(index, 10)
|
name := strconv.FormatInt(index, 10)
|
||||||
if object.hasProperty(name) {
|
if obj.hasProperty(name) {
|
||||||
valueArray = append(valueArray, object.get(name))
|
valueArray = append(valueArray, obj.get(name))
|
||||||
} else {
|
} else {
|
||||||
valueArray = append(valueArray, Value{})
|
valueArray = append(valueArray, Value{})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
fallthrough
|
fallthrough
|
||||||
default:
|
default:
|
||||||
valueArray = append(valueArray, item)
|
valueArray = append(valueArray, item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return toValue_object(call.runtime.newArrayOf(valueArray))
|
return objectValue(call.runtime.newArrayOf(valueArray))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinArray_shift(call FunctionCall) Value {
|
func builtinArrayShift(call FunctionCall) Value {
|
||||||
thisObject := call.thisObject()
|
thisObject := call.thisObject()
|
||||||
length := int64(toUint32(thisObject.get(propertyLength)))
|
length := int64(toUint32(thisObject.get(propertyLength)))
|
||||||
if 0 == length {
|
if length == 0 {
|
||||||
thisObject.put(propertyLength, toValue_int64(0), true)
|
thisObject.put(propertyLength, int64Value(0), true)
|
||||||
return Value{}
|
return Value{}
|
||||||
}
|
}
|
||||||
first := thisObject.get("0")
|
first := thisObject.get("0")
|
||||||
|
@ -107,52 +108,50 @@ func builtinArray_shift(call FunctionCall) Value {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
thisObject.delete(arrayIndexToString(length-1), true)
|
thisObject.delete(arrayIndexToString(length-1), true)
|
||||||
thisObject.put(propertyLength, toValue_int64(length-1), true)
|
thisObject.put(propertyLength, int64Value(length-1), true)
|
||||||
return first
|
return first
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinArray_push(call FunctionCall) Value {
|
func builtinArrayPush(call FunctionCall) Value {
|
||||||
thisObject := call.thisObject()
|
thisObject := call.thisObject()
|
||||||
itemList := call.ArgumentList
|
itemList := call.ArgumentList
|
||||||
index := int64(toUint32(thisObject.get(propertyLength)))
|
index := int64(toUint32(thisObject.get(propertyLength)))
|
||||||
for len(itemList) > 0 {
|
for len(itemList) > 0 {
|
||||||
thisObject.put(arrayIndexToString(index), itemList[0], true)
|
thisObject.put(arrayIndexToString(index), itemList[0], true)
|
||||||
itemList = itemList[1:]
|
itemList = itemList[1:]
|
||||||
index += 1
|
index++
|
||||||
}
|
}
|
||||||
length := toValue_int64(index)
|
length := int64Value(index)
|
||||||
thisObject.put(propertyLength, length, true)
|
thisObject.put(propertyLength, length, true)
|
||||||
return length
|
return length
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinArray_pop(call FunctionCall) Value {
|
func builtinArrayPop(call FunctionCall) Value {
|
||||||
thisObject := call.thisObject()
|
thisObject := call.thisObject()
|
||||||
length := int64(toUint32(thisObject.get(propertyLength)))
|
length := int64(toUint32(thisObject.get(propertyLength)))
|
||||||
if 0 == length {
|
if length == 0 {
|
||||||
thisObject.put(propertyLength, toValue_uint32(0), true)
|
thisObject.put(propertyLength, uint32Value(0), true)
|
||||||
return Value{}
|
return Value{}
|
||||||
}
|
}
|
||||||
last := thisObject.get(arrayIndexToString(length - 1))
|
last := thisObject.get(arrayIndexToString(length - 1))
|
||||||
thisObject.delete(arrayIndexToString(length-1), true)
|
thisObject.delete(arrayIndexToString(length-1), true)
|
||||||
thisObject.put(propertyLength, toValue_int64(length-1), true)
|
thisObject.put(propertyLength, int64Value(length-1), true)
|
||||||
return last
|
return last
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinArray_join(call FunctionCall) Value {
|
func builtinArrayJoin(call FunctionCall) Value {
|
||||||
separator := ","
|
separator := ","
|
||||||
{
|
|
||||||
argument := call.Argument(0)
|
argument := call.Argument(0)
|
||||||
if argument.IsDefined() {
|
if argument.IsDefined() {
|
||||||
separator = argument.string()
|
separator = argument.string()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
thisObject := call.thisObject()
|
thisObject := call.thisObject()
|
||||||
length := int64(toUint32(thisObject.get(propertyLength)))
|
length := int64(toUint32(thisObject.get(propertyLength)))
|
||||||
if length == 0 {
|
if length == 0 {
|
||||||
return toValue_string("")
|
return stringValue("")
|
||||||
}
|
}
|
||||||
stringList := make([]string, 0, length)
|
stringList := make([]string, 0, length)
|
||||||
for index := int64(0); index < length; index += 1 {
|
for index := int64(0); index < length; index++ {
|
||||||
value := thisObject.get(arrayIndexToString(index))
|
value := thisObject.get(arrayIndexToString(index))
|
||||||
stringValue := ""
|
stringValue := ""
|
||||||
switch value.kind {
|
switch value.kind {
|
||||||
|
@ -162,10 +161,10 @@ func builtinArray_join(call FunctionCall) Value {
|
||||||
}
|
}
|
||||||
stringList = append(stringList, stringValue)
|
stringList = append(stringList, stringValue)
|
||||||
}
|
}
|
||||||
return toValue_string(strings.Join(stringList, separator))
|
return stringValue(strings.Join(stringList, separator))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinArray_splice(call FunctionCall) Value {
|
func builtinArraySplice(call FunctionCall) Value {
|
||||||
thisObject := call.thisObject()
|
thisObject := call.thisObject()
|
||||||
length := int64(toUint32(thisObject.get(propertyLength)))
|
length := int64(toUint32(thisObject.get(propertyLength)))
|
||||||
|
|
||||||
|
@ -177,7 +176,7 @@ func builtinArray_splice(call FunctionCall) Value {
|
||||||
valueArray := make([]Value, deleteCount)
|
valueArray := make([]Value, deleteCount)
|
||||||
|
|
||||||
for index := int64(0); index < deleteCount; index++ {
|
for index := int64(0); index < deleteCount; index++ {
|
||||||
indexString := arrayIndexToString(int64(start + index))
|
indexString := arrayIndexToString(start + index)
|
||||||
if thisObject.hasProperty(indexString) {
|
if thisObject.hasProperty(indexString) {
|
||||||
valueArray[index] = thisObject.get(indexString)
|
valueArray[index] = thisObject.get(indexString)
|
||||||
}
|
}
|
||||||
|
@ -197,7 +196,7 @@ func builtinArray_splice(call FunctionCall) Value {
|
||||||
}
|
}
|
||||||
if itemCount < deleteCount {
|
if itemCount < deleteCount {
|
||||||
// The Object/Array is shrinking
|
// The Object/Array is shrinking
|
||||||
stop := int64(length) - deleteCount
|
stop := length - deleteCount
|
||||||
// The new length of the Object/Array before
|
// The new length of the Object/Array before
|
||||||
// appending the itemList remainder
|
// appending the itemList remainder
|
||||||
// Stopping at the lower bound of the insertion:
|
// Stopping at the lower bound of the insertion:
|
||||||
|
@ -215,7 +214,7 @@ func builtinArray_splice(call FunctionCall) Value {
|
||||||
// Delete off the end
|
// Delete off the end
|
||||||
// We don't bother to delete below <stop + itemCount> (if any) since those
|
// We don't bother to delete below <stop + itemCount> (if any) since those
|
||||||
// will be overwritten anyway
|
// will be overwritten anyway
|
||||||
for index := int64(length); index > (stop + itemCount); index-- {
|
for index := length; index > (stop + itemCount); index-- {
|
||||||
thisObject.delete(arrayIndexToString(index-1), true)
|
thisObject.delete(arrayIndexToString(index-1), true)
|
||||||
}
|
}
|
||||||
} else if itemCount > deleteCount {
|
} else if itemCount > deleteCount {
|
||||||
|
@ -226,7 +225,7 @@ func builtinArray_splice(call FunctionCall) Value {
|
||||||
// Starting from the upper bound of the deletion:
|
// Starting from the upper bound of the deletion:
|
||||||
// Move an item from the after the deleted portion
|
// Move an item from the after the deleted portion
|
||||||
// to a position after the inserted portion
|
// to a position after the inserted portion
|
||||||
for index := int64(length) - deleteCount; index > start; index-- {
|
for index := length - deleteCount; index > start; index-- {
|
||||||
from := arrayIndexToString(index + deleteCount - 1)
|
from := arrayIndexToString(index + deleteCount - 1)
|
||||||
to := arrayIndexToString(index + itemCount - 1)
|
to := arrayIndexToString(index + itemCount - 1)
|
||||||
if thisObject.hasProperty(from) {
|
if thisObject.hasProperty(from) {
|
||||||
|
@ -240,12 +239,12 @@ func builtinArray_splice(call FunctionCall) Value {
|
||||||
for index := int64(0); index < itemCount; index++ {
|
for index := int64(0); index < itemCount; index++ {
|
||||||
thisObject.put(arrayIndexToString(index+start), itemList[index], true)
|
thisObject.put(arrayIndexToString(index+start), itemList[index], true)
|
||||||
}
|
}
|
||||||
thisObject.put(propertyLength, toValue_int64(int64(length)+itemCount-deleteCount), true)
|
thisObject.put(propertyLength, int64Value(length+itemCount-deleteCount), true)
|
||||||
|
|
||||||
return toValue_object(call.runtime.newArrayOf(valueArray))
|
return objectValue(call.runtime.newArrayOf(valueArray))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinArray_slice(call FunctionCall) Value {
|
func builtinArraySlice(call FunctionCall) Value {
|
||||||
thisObject := call.thisObject()
|
thisObject := call.thisObject()
|
||||||
|
|
||||||
length := int64(toUint32(thisObject.get(propertyLength)))
|
length := int64(toUint32(thisObject.get(propertyLength)))
|
||||||
|
@ -253,7 +252,7 @@ func builtinArray_slice(call FunctionCall) Value {
|
||||||
|
|
||||||
if start >= end {
|
if start >= end {
|
||||||
// Always an empty array
|
// Always an empty array
|
||||||
return toValue_object(call.runtime.newArray(0))
|
return objectValue(call.runtime.newArray(0))
|
||||||
}
|
}
|
||||||
sliceLength := end - start
|
sliceLength := end - start
|
||||||
sliceValueArray := make([]Value, sliceLength)
|
sliceValueArray := make([]Value, sliceLength)
|
||||||
|
@ -265,10 +264,10 @@ func builtinArray_slice(call FunctionCall) Value {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return toValue_object(call.runtime.newArrayOf(sliceValueArray))
|
return objectValue(call.runtime.newArrayOf(sliceValueArray))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinArray_unshift(call FunctionCall) Value {
|
func builtinArrayUnshift(call FunctionCall) Value {
|
||||||
thisObject := call.thisObject()
|
thisObject := call.thisObject()
|
||||||
length := int64(toUint32(thisObject.get(propertyLength)))
|
length := int64(toUint32(thisObject.get(propertyLength)))
|
||||||
itemList := call.ArgumentList
|
itemList := call.ArgumentList
|
||||||
|
@ -288,12 +287,12 @@ func builtinArray_unshift(call FunctionCall) Value {
|
||||||
thisObject.put(arrayIndexToString(index), itemList[index], true)
|
thisObject.put(arrayIndexToString(index), itemList[index], true)
|
||||||
}
|
}
|
||||||
|
|
||||||
newLength := toValue_int64(length + itemCount)
|
newLength := int64Value(length + itemCount)
|
||||||
thisObject.put(propertyLength, newLength, true)
|
thisObject.put(propertyLength, newLength, true)
|
||||||
return newLength
|
return newLength
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinArray_reverse(call FunctionCall) Value {
|
func builtinArrayReverse(call FunctionCall) Value {
|
||||||
thisObject := call.thisObject()
|
thisObject := call.thisObject()
|
||||||
length := int64(toUint32(thisObject.get(propertyLength)))
|
length := int64(toUint32(thisObject.get(propertyLength)))
|
||||||
|
|
||||||
|
@ -315,30 +314,29 @@ func builtinArray_reverse(call FunctionCall) Value {
|
||||||
lower.exists = thisObject.hasProperty(lower.name)
|
lower.exists = thisObject.hasProperty(lower.name)
|
||||||
upper.exists = thisObject.hasProperty(upper.name)
|
upper.exists = thisObject.hasProperty(upper.name)
|
||||||
|
|
||||||
if lower.exists && upper.exists {
|
switch {
|
||||||
|
case lower.exists && upper.exists:
|
||||||
lowerValue := thisObject.get(lower.name)
|
lowerValue := thisObject.get(lower.name)
|
||||||
upperValue := thisObject.get(upper.name)
|
upperValue := thisObject.get(upper.name)
|
||||||
thisObject.put(lower.name, upperValue, true)
|
thisObject.put(lower.name, upperValue, true)
|
||||||
thisObject.put(upper.name, lowerValue, true)
|
thisObject.put(upper.name, lowerValue, true)
|
||||||
} else if !lower.exists && upper.exists {
|
case !lower.exists && upper.exists:
|
||||||
value := thisObject.get(upper.name)
|
value := thisObject.get(upper.name)
|
||||||
thisObject.delete(upper.name, true)
|
thisObject.delete(upper.name, true)
|
||||||
thisObject.put(lower.name, value, true)
|
thisObject.put(lower.name, value, true)
|
||||||
} else if lower.exists && !upper.exists {
|
case lower.exists && !upper.exists:
|
||||||
value := thisObject.get(lower.name)
|
value := thisObject.get(lower.name)
|
||||||
thisObject.delete(lower.name, true)
|
thisObject.delete(lower.name, true)
|
||||||
thisObject.put(upper.name, value, true)
|
thisObject.put(upper.name, value, true)
|
||||||
} else {
|
|
||||||
// Nothing happens.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lower.index += 1
|
lower.index++
|
||||||
}
|
}
|
||||||
|
|
||||||
return call.This
|
return call.This
|
||||||
}
|
}
|
||||||
|
|
||||||
func sortCompare(thisObject *_object, index0, index1 uint, compare *_object) int {
|
func sortCompare(thisObject *object, index0, index1 uint, compare *object) int {
|
||||||
j := struct {
|
j := struct {
|
||||||
name string
|
name string
|
||||||
exists bool
|
exists bool
|
||||||
|
@ -351,11 +349,12 @@ func sortCompare(thisObject *_object, index0, index1 uint, compare *_object) int
|
||||||
k.name = arrayIndexToString(int64(index1))
|
k.name = arrayIndexToString(int64(index1))
|
||||||
k.exists = thisObject.hasProperty(k.name)
|
k.exists = thisObject.hasProperty(k.name)
|
||||||
|
|
||||||
if !j.exists && !k.exists {
|
switch {
|
||||||
|
case !j.exists && !k.exists:
|
||||||
return 0
|
return 0
|
||||||
} else if !j.exists {
|
case !j.exists:
|
||||||
return 1
|
return 1
|
||||||
} else if !k.exists {
|
case !k.exists:
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -364,11 +363,12 @@ func sortCompare(thisObject *_object, index0, index1 uint, compare *_object) int
|
||||||
j.defined = x.IsDefined()
|
j.defined = x.IsDefined()
|
||||||
k.defined = y.IsDefined()
|
k.defined = y.IsDefined()
|
||||||
|
|
||||||
if !j.defined && !k.defined {
|
switch {
|
||||||
|
case !j.defined && !k.defined:
|
||||||
return 0
|
return 0
|
||||||
} else if !j.defined {
|
case !j.defined:
|
||||||
return 1
|
return 1
|
||||||
} else if !k.defined {
|
case !k.defined:
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -388,7 +388,7 @@ func sortCompare(thisObject *_object, index0, index1 uint, compare *_object) int
|
||||||
return toIntSign(compare.call(Value{}, []Value{x, y}, false, nativeFrame))
|
return toIntSign(compare.call(Value{}, []Value{x, y}, false, nativeFrame))
|
||||||
}
|
}
|
||||||
|
|
||||||
func arraySortSwap(thisObject *_object, index0, index1 uint) {
|
func arraySortSwap(thisObject *object, index0, index1 uint) {
|
||||||
j := struct {
|
j := struct {
|
||||||
name string
|
name string
|
||||||
exists bool
|
exists bool
|
||||||
|
@ -400,25 +400,24 @@ func arraySortSwap(thisObject *_object, index0, index1 uint) {
|
||||||
k.name = arrayIndexToString(int64(index1))
|
k.name = arrayIndexToString(int64(index1))
|
||||||
k.exists = thisObject.hasProperty(k.name)
|
k.exists = thisObject.hasProperty(k.name)
|
||||||
|
|
||||||
if j.exists && k.exists {
|
switch {
|
||||||
jValue := thisObject.get(j.name)
|
case j.exists && k.exists:
|
||||||
kValue := thisObject.get(k.name)
|
jv := thisObject.get(j.name)
|
||||||
thisObject.put(j.name, kValue, true)
|
kv := thisObject.get(k.name)
|
||||||
thisObject.put(k.name, jValue, true)
|
thisObject.put(j.name, kv, true)
|
||||||
} else if !j.exists && k.exists {
|
thisObject.put(k.name, jv, true)
|
||||||
|
case !j.exists && k.exists:
|
||||||
value := thisObject.get(k.name)
|
value := thisObject.get(k.name)
|
||||||
thisObject.delete(k.name, true)
|
thisObject.delete(k.name, true)
|
||||||
thisObject.put(j.name, value, true)
|
thisObject.put(j.name, value, true)
|
||||||
} else if j.exists && !k.exists {
|
case j.exists && !k.exists:
|
||||||
value := thisObject.get(j.name)
|
value := thisObject.get(j.name)
|
||||||
thisObject.delete(j.name, true)
|
thisObject.delete(j.name, true)
|
||||||
thisObject.put(k.name, value, true)
|
thisObject.put(k.name, value, true)
|
||||||
} else {
|
|
||||||
// Nothing happens.
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func arraySortQuickPartition(thisObject *_object, left, right, pivot uint, compare *_object) (uint, uint) {
|
func arraySortQuickPartition(thisObject *object, left, right, pivot uint, compare *object) (uint, uint) {
|
||||||
arraySortSwap(thisObject, pivot, right) // Right is now the pivot value
|
arraySortSwap(thisObject, pivot, right) // Right is now the pivot value
|
||||||
cursor := left
|
cursor := left
|
||||||
cursor2 := left
|
cursor2 := left
|
||||||
|
@ -429,18 +428,18 @@ func arraySortQuickPartition(thisObject *_object, left, right, pivot uint, compa
|
||||||
if cursor < cursor2 {
|
if cursor < cursor2 {
|
||||||
arraySortSwap(thisObject, index, cursor2)
|
arraySortSwap(thisObject, index, cursor2)
|
||||||
}
|
}
|
||||||
cursor += 1
|
cursor++
|
||||||
cursor2 += 1
|
cursor2++
|
||||||
} else if comparison == 0 {
|
} else if comparison == 0 {
|
||||||
arraySortSwap(thisObject, index, cursor2)
|
arraySortSwap(thisObject, index, cursor2)
|
||||||
cursor2 += 1
|
cursor2++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
arraySortSwap(thisObject, cursor2, right)
|
arraySortSwap(thisObject, cursor2, right)
|
||||||
return cursor, cursor2
|
return cursor, cursor2
|
||||||
}
|
}
|
||||||
|
|
||||||
func arraySortQuickSort(thisObject *_object, left, right uint, compare *_object) {
|
func arraySortQuickSort(thisObject *object, left, right uint, compare *object) {
|
||||||
if left < right {
|
if left < right {
|
||||||
middle := left + (right-left)/2
|
middle := left + (right-left)/2
|
||||||
pivot, pivot2 := arraySortQuickPartition(thisObject, left, right, middle, compare)
|
pivot, pivot2 := arraySortQuickPartition(thisObject, left, right, middle, compare)
|
||||||
|
@ -451,14 +450,14 @@ func arraySortQuickSort(thisObject *_object, left, right uint, compare *_object)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinArray_sort(call FunctionCall) Value {
|
func builtinArraySort(call FunctionCall) Value {
|
||||||
thisObject := call.thisObject()
|
thisObject := call.thisObject()
|
||||||
length := uint(toUint32(thisObject.get(propertyLength)))
|
length := uint(toUint32(thisObject.get(propertyLength)))
|
||||||
compareValue := call.Argument(0)
|
compareValue := call.Argument(0)
|
||||||
compare := compareValue._object()
|
compare := compareValue.object()
|
||||||
if compareValue.IsUndefined() {
|
if compareValue.IsUndefined() {
|
||||||
} else if !compareValue.isCallable() {
|
} else if !compareValue.isCallable() {
|
||||||
panic(call.runtime.panicTypeError())
|
panic(call.runtime.panicTypeError("Array.sort value %q is not callable", compareValue))
|
||||||
}
|
}
|
||||||
if length > 1 {
|
if length > 1 {
|
||||||
arraySortQuickSort(thisObject, 0, length-1, compare)
|
arraySortQuickSort(thisObject, 0, length-1, compare)
|
||||||
|
@ -466,11 +465,11 @@ func builtinArray_sort(call FunctionCall) Value {
|
||||||
return call.This
|
return call.This
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinArray_isArray(call FunctionCall) Value {
|
func builtinArrayIsArray(call FunctionCall) Value {
|
||||||
return toValue_bool(isArray(call.Argument(0)._object()))
|
return boolValue(isArray(call.Argument(0).object()))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinArray_indexOf(call FunctionCall) Value {
|
func builtinArrayIndexOf(call FunctionCall) Value {
|
||||||
thisObject, matchValue := call.thisObject(), call.Argument(0)
|
thisObject, matchValue := call.thisObject(), call.Argument(0)
|
||||||
if length := int64(toUint32(thisObject.get(propertyLength))); length > 0 {
|
if length := int64(toUint32(thisObject.get(propertyLength))); length > 0 {
|
||||||
index := int64(0)
|
index := int64(0)
|
||||||
|
@ -485,20 +484,20 @@ func builtinArray_indexOf(call FunctionCall) Value {
|
||||||
index = -1
|
index = -1
|
||||||
}
|
}
|
||||||
for ; index >= 0 && index < length; index++ {
|
for ; index >= 0 && index < length; index++ {
|
||||||
name := arrayIndexToString(int64(index))
|
name := arrayIndexToString(index)
|
||||||
if !thisObject.hasProperty(name) {
|
if !thisObject.hasProperty(name) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
value := thisObject.get(name)
|
value := thisObject.get(name)
|
||||||
if strictEqualityComparison(matchValue, value) {
|
if strictEqualityComparison(matchValue, value) {
|
||||||
return toValue_uint32(uint32(index))
|
return uint32Value(uint32(index))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return toValue_int(-1)
|
return intValue(-1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinArray_lastIndexOf(call FunctionCall) Value {
|
func builtinArrayLastIndexOf(call FunctionCall) Value {
|
||||||
thisObject, matchValue := call.thisObject(), call.Argument(0)
|
thisObject, matchValue := call.thisObject(), call.Argument(0)
|
||||||
length := int64(toUint32(thisObject.get(propertyLength)))
|
length := int64(toUint32(thisObject.get(propertyLength)))
|
||||||
index := length - 1
|
index := length - 1
|
||||||
|
@ -511,30 +510,30 @@ func builtinArray_lastIndexOf(call FunctionCall) Value {
|
||||||
if index > length {
|
if index > length {
|
||||||
index = length - 1
|
index = length - 1
|
||||||
} else if 0 > index {
|
} else if 0 > index {
|
||||||
return toValue_int(-1)
|
return intValue(-1)
|
||||||
}
|
}
|
||||||
for ; index >= 0; index-- {
|
for ; index >= 0; index-- {
|
||||||
name := arrayIndexToString(int64(index))
|
name := arrayIndexToString(index)
|
||||||
if !thisObject.hasProperty(name) {
|
if !thisObject.hasProperty(name) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
value := thisObject.get(name)
|
value := thisObject.get(name)
|
||||||
if strictEqualityComparison(matchValue, value) {
|
if strictEqualityComparison(matchValue, value) {
|
||||||
return toValue_uint32(uint32(index))
|
return uint32Value(uint32(index))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return toValue_int(-1)
|
return intValue(-1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinArray_every(call FunctionCall) Value {
|
func builtinArrayEvery(call FunctionCall) Value {
|
||||||
thisObject := call.thisObject()
|
thisObject := call.thisObject()
|
||||||
this := toValue_object(thisObject)
|
this := objectValue(thisObject)
|
||||||
if iterator := call.Argument(0); iterator.isCallable() {
|
if iterator := call.Argument(0); iterator.isCallable() {
|
||||||
length := int64(toUint32(thisObject.get(propertyLength)))
|
length := int64(toUint32(thisObject.get(propertyLength)))
|
||||||
callThis := call.Argument(1)
|
callThis := call.Argument(1)
|
||||||
for index := int64(0); index < length; index++ {
|
for index := int64(0); index < length; index++ {
|
||||||
if key := arrayIndexToString(index); thisObject.hasProperty(key) {
|
if key := arrayIndexToString(index); thisObject.hasProperty(key) {
|
||||||
if value := thisObject.get(key); iterator.call(call.runtime, callThis, value, toValue_int64(index), this).bool() {
|
if value := thisObject.get(key); iterator.call(call.runtime, callThis, value, int64Value(index), this).bool() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
return falseValue
|
return falseValue
|
||||||
|
@ -542,46 +541,46 @@ func builtinArray_every(call FunctionCall) Value {
|
||||||
}
|
}
|
||||||
return trueValue
|
return trueValue
|
||||||
}
|
}
|
||||||
panic(call.runtime.panicTypeError())
|
panic(call.runtime.panicTypeError("Array.every argument %q is not callable", call.Argument(0)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinArray_some(call FunctionCall) Value {
|
func builtinArraySome(call FunctionCall) Value {
|
||||||
thisObject := call.thisObject()
|
thisObject := call.thisObject()
|
||||||
this := toValue_object(thisObject)
|
this := objectValue(thisObject)
|
||||||
if iterator := call.Argument(0); iterator.isCallable() {
|
if iterator := call.Argument(0); iterator.isCallable() {
|
||||||
length := int64(toUint32(thisObject.get(propertyLength)))
|
length := int64(toUint32(thisObject.get(propertyLength)))
|
||||||
callThis := call.Argument(1)
|
callThis := call.Argument(1)
|
||||||
for index := int64(0); index < length; index++ {
|
for index := int64(0); index < length; index++ {
|
||||||
if key := arrayIndexToString(index); thisObject.hasProperty(key) {
|
if key := arrayIndexToString(index); thisObject.hasProperty(key) {
|
||||||
if value := thisObject.get(key); iterator.call(call.runtime, callThis, value, toValue_int64(index), this).bool() {
|
if value := thisObject.get(key); iterator.call(call.runtime, callThis, value, int64Value(index), this).bool() {
|
||||||
return trueValue
|
return trueValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return falseValue
|
return falseValue
|
||||||
}
|
}
|
||||||
panic(call.runtime.panicTypeError())
|
panic(call.runtime.panicTypeError("Array.some %q if not callable", call.Argument(0)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinArray_forEach(call FunctionCall) Value {
|
func builtinArrayForEach(call FunctionCall) Value {
|
||||||
thisObject := call.thisObject()
|
thisObject := call.thisObject()
|
||||||
this := toValue_object(thisObject)
|
this := objectValue(thisObject)
|
||||||
if iterator := call.Argument(0); iterator.isCallable() {
|
if iterator := call.Argument(0); iterator.isCallable() {
|
||||||
length := int64(toUint32(thisObject.get(propertyLength)))
|
length := int64(toUint32(thisObject.get(propertyLength)))
|
||||||
callThis := call.Argument(1)
|
callThis := call.Argument(1)
|
||||||
for index := int64(0); index < length; index++ {
|
for index := int64(0); index < length; index++ {
|
||||||
if key := arrayIndexToString(index); thisObject.hasProperty(key) {
|
if key := arrayIndexToString(index); thisObject.hasProperty(key) {
|
||||||
iterator.call(call.runtime, callThis, thisObject.get(key), toValue_int64(index), this)
|
iterator.call(call.runtime, callThis, thisObject.get(key), int64Value(index), this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Value{}
|
return Value{}
|
||||||
}
|
}
|
||||||
panic(call.runtime.panicTypeError())
|
panic(call.runtime.panicTypeError("Array.foreach %q if not callable", call.Argument(0)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinArray_map(call FunctionCall) Value {
|
func builtinArrayMap(call FunctionCall) Value {
|
||||||
thisObject := call.thisObject()
|
thisObject := call.thisObject()
|
||||||
this := toValue_object(thisObject)
|
this := objectValue(thisObject)
|
||||||
if iterator := call.Argument(0); iterator.isCallable() {
|
if iterator := call.Argument(0); iterator.isCallable() {
|
||||||
length := int64(toUint32(thisObject.get(propertyLength)))
|
length := int64(toUint32(thisObject.get(propertyLength)))
|
||||||
callThis := call.Argument(1)
|
callThis := call.Argument(1)
|
||||||
|
@ -593,14 +592,14 @@ func builtinArray_map(call FunctionCall) Value {
|
||||||
values[index] = Value{}
|
values[index] = Value{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return toValue_object(call.runtime.newArrayOf(values))
|
return objectValue(call.runtime.newArrayOf(values))
|
||||||
}
|
}
|
||||||
panic(call.runtime.panicTypeError())
|
panic(call.runtime.panicTypeError("Array.foreach %q if not callable", call.Argument(0)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinArray_filter(call FunctionCall) Value {
|
func builtinArrayFilter(call FunctionCall) Value {
|
||||||
thisObject := call.thisObject()
|
thisObject := call.thisObject()
|
||||||
this := toValue_object(thisObject)
|
this := objectValue(thisObject)
|
||||||
if iterator := call.Argument(0); iterator.isCallable() {
|
if iterator := call.Argument(0); iterator.isCallable() {
|
||||||
length := int64(toUint32(thisObject.get(propertyLength)))
|
length := int64(toUint32(thisObject.get(propertyLength)))
|
||||||
callThis := call.Argument(1)
|
callThis := call.Argument(1)
|
||||||
|
@ -613,14 +612,14 @@ func builtinArray_filter(call FunctionCall) Value {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return toValue_object(call.runtime.newArrayOf(values))
|
return objectValue(call.runtime.newArrayOf(values))
|
||||||
}
|
}
|
||||||
panic(call.runtime.panicTypeError())
|
panic(call.runtime.panicTypeError("Array.filter %q if not callable", call.Argument(0)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinArray_reduce(call FunctionCall) Value {
|
func builtinArrayReduce(call FunctionCall) Value {
|
||||||
thisObject := call.thisObject()
|
thisObject := call.thisObject()
|
||||||
this := toValue_object(thisObject)
|
this := objectValue(thisObject)
|
||||||
if iterator := call.Argument(0); iterator.isCallable() {
|
if iterator := call.Argument(0); iterator.isCallable() {
|
||||||
initial := len(call.ArgumentList) > 1
|
initial := len(call.ArgumentList) > 1
|
||||||
start := call.Argument(1)
|
start := call.Argument(1)
|
||||||
|
@ -633,6 +632,7 @@ func builtinArray_reduce(call FunctionCall) Value {
|
||||||
if key := arrayIndexToString(index); thisObject.hasProperty(key) {
|
if key := arrayIndexToString(index); thisObject.hasProperty(key) {
|
||||||
accumulator = thisObject.get(key)
|
accumulator = thisObject.get(key)
|
||||||
index++
|
index++
|
||||||
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -647,12 +647,12 @@ func builtinArray_reduce(call FunctionCall) Value {
|
||||||
return accumulator
|
return accumulator
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
panic(call.runtime.panicTypeError())
|
panic(call.runtime.panicTypeError("Array.reduce %q if not callable", call.Argument(0)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinArray_reduceRight(call FunctionCall) Value {
|
func builtinArrayReduceRight(call FunctionCall) Value {
|
||||||
thisObject := call.thisObject()
|
thisObject := call.thisObject()
|
||||||
this := toValue_object(thisObject)
|
this := objectValue(thisObject)
|
||||||
if iterator := call.Argument(0); iterator.isCallable() {
|
if iterator := call.Argument(0); iterator.isCallable() {
|
||||||
initial := len(call.ArgumentList) > 1
|
initial := len(call.ArgumentList) > 1
|
||||||
start := call.Argument(1)
|
start := call.Argument(1)
|
||||||
|
@ -679,5 +679,5 @@ func builtinArray_reduceRight(call FunctionCall) Value {
|
||||||
return accumulator
|
return accumulator
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
panic(call.runtime.panicTypeError())
|
panic(call.runtime.panicTypeError("Array.reduceRight %q if not callable", call.Argument(0)))
|
||||||
}
|
}
|
||||||
|
|
16
v1/vendor/github.com/robertkrimen/otto/builtin_boolean.go
generated
vendored
|
@ -3,26 +3,26 @@ package otto
|
||||||
// Boolean
|
// Boolean
|
||||||
|
|
||||||
func builtinBoolean(call FunctionCall) Value {
|
func builtinBoolean(call FunctionCall) Value {
|
||||||
return toValue_bool(call.Argument(0).bool())
|
return boolValue(call.Argument(0).bool())
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinNewBoolean(self *_object, argumentList []Value) Value {
|
func builtinNewBoolean(obj *object, argumentList []Value) Value {
|
||||||
return toValue_object(self.runtime.newBoolean(valueOfArrayIndex(argumentList, 0)))
|
return objectValue(obj.runtime.newBoolean(valueOfArrayIndex(argumentList, 0)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinBoolean_toString(call FunctionCall) Value {
|
func builtinBooleanToString(call FunctionCall) Value {
|
||||||
value := call.This
|
value := call.This
|
||||||
if !value.IsBoolean() {
|
if !value.IsBoolean() {
|
||||||
// Will throw a TypeError if ThisObject is not a Boolean
|
// Will throw a TypeError if ThisObject is not a Boolean
|
||||||
value = call.thisClassObject(classBoolean).primitiveValue()
|
value = call.thisClassObject(classBooleanName).primitiveValue()
|
||||||
}
|
}
|
||||||
return toValue_string(value.string())
|
return stringValue(value.string())
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinBoolean_valueOf(call FunctionCall) Value {
|
func builtinBooleanValueOf(call FunctionCall) Value {
|
||||||
value := call.This
|
value := call.This
|
||||||
if !value.IsBoolean() {
|
if !value.IsBoolean() {
|
||||||
value = call.thisClassObject(classBoolean).primitiveValue()
|
value = call.thisClassObject(classBooleanName).primitiveValue()
|
||||||
}
|
}
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
|
|
333
v1/vendor/github.com/robertkrimen/otto/builtin_date.go
generated
vendored
|
@ -2,121 +2,118 @@ package otto
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"math"
|
"math"
|
||||||
Time "time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Date
|
// Date
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// TODO Be like V8?
|
// TODO Be like V8?
|
||||||
// builtinDate_goDateTimeLayout = "Mon Jan 2 2006 15:04:05 GMT-0700 (MST)"
|
// builtinDateDateTimeLayout = "Mon Jan 2 2006 15:04:05 GMT-0700 (MST)".
|
||||||
builtinDate_goDateTimeLayout = Time.RFC1123 // "Mon, 02 Jan 2006 15:04:05 MST"
|
builtinDateDateTimeLayout = time.RFC1123 // "Mon, 02 Jan 2006 15:04:05 MST"
|
||||||
builtinDate_goDateLayout = "Mon, 02 Jan 2006"
|
builtinDateDateLayout = "Mon, 02 Jan 2006"
|
||||||
builtinDate_goTimeLayout = "15:04:05 MST"
|
builtinDateTimeLayout = "15:04:05 MST"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
|
||||||
// utcTimeZone is the time zone used for UTC calculations.
|
// utcTimeZone is the time zone used for UTC calculations.
|
||||||
// It is GMT not UTC as that's what Javascript does because toUTCString is
|
// It is GMT not UTC as that's what Javascript does because toUTCString is
|
||||||
// actually an alias to toGMTString.
|
// actually an alias to toGMTString.
|
||||||
utcTimeZone = Time.FixedZone("GMT", 0)
|
var utcTimeZone = time.FixedZone("GMT", 0)
|
||||||
)
|
|
||||||
|
|
||||||
func builtinDate(call FunctionCall) Value {
|
func builtinDate(call FunctionCall) Value {
|
||||||
date := &_dateObject{}
|
date := &dateObject{}
|
||||||
date.Set(newDateTime([]Value{}, Time.Local))
|
date.Set(newDateTime([]Value{}, time.Local)) //nolint: gosmopolitan
|
||||||
return toValue_string(date.Time().Format(builtinDate_goDateTimeLayout))
|
return stringValue(date.Time().Format(builtinDateDateTimeLayout))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinNewDate(self *_object, argumentList []Value) Value {
|
func builtinNewDate(obj *object, argumentList []Value) Value {
|
||||||
return toValue_object(self.runtime.newDate(newDateTime(argumentList, Time.Local)))
|
return objectValue(obj.runtime.newDate(newDateTime(argumentList, time.Local))) //nolint: gosmopolitan
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinDate_toString(call FunctionCall) Value {
|
func builtinDateToString(call FunctionCall) Value {
|
||||||
date := dateObjectOf(call.runtime, call.thisObject())
|
date := dateObjectOf(call.runtime, call.thisObject())
|
||||||
if date.isNaN {
|
if date.isNaN {
|
||||||
return toValue_string("Invalid Date")
|
return stringValue("Invalid Date")
|
||||||
}
|
}
|
||||||
return toValue_string(date.Time().Local().Format(builtinDate_goDateTimeLayout))
|
return stringValue(date.Time().Local().Format(builtinDateDateTimeLayout)) //nolint: gosmopolitan
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinDate_toDateString(call FunctionCall) Value {
|
func builtinDateToDateString(call FunctionCall) Value {
|
||||||
date := dateObjectOf(call.runtime, call.thisObject())
|
date := dateObjectOf(call.runtime, call.thisObject())
|
||||||
if date.isNaN {
|
if date.isNaN {
|
||||||
return toValue_string("Invalid Date")
|
return stringValue("Invalid Date")
|
||||||
}
|
}
|
||||||
return toValue_string(date.Time().Local().Format(builtinDate_goDateLayout))
|
return stringValue(date.Time().Local().Format(builtinDateDateLayout)) //nolint: gosmopolitan
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinDate_toTimeString(call FunctionCall) Value {
|
func builtinDateToTimeString(call FunctionCall) Value {
|
||||||
date := dateObjectOf(call.runtime, call.thisObject())
|
date := dateObjectOf(call.runtime, call.thisObject())
|
||||||
if date.isNaN {
|
if date.isNaN {
|
||||||
return toValue_string("Invalid Date")
|
return stringValue("Invalid Date")
|
||||||
}
|
}
|
||||||
return toValue_string(date.Time().Local().Format(builtinDate_goTimeLayout))
|
return stringValue(date.Time().Local().Format(builtinDateTimeLayout)) //nolint: gosmopolitan
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinDate_toUTCString(call FunctionCall) Value {
|
func builtinDateToUTCString(call FunctionCall) Value {
|
||||||
date := dateObjectOf(call.runtime, call.thisObject())
|
date := dateObjectOf(call.runtime, call.thisObject())
|
||||||
if date.isNaN {
|
if date.isNaN {
|
||||||
return toValue_string("Invalid Date")
|
return stringValue("Invalid Date")
|
||||||
}
|
}
|
||||||
return toValue_string(date.Time().In(utcTimeZone).Format(builtinDate_goDateTimeLayout))
|
return stringValue(date.Time().In(utcTimeZone).Format(builtinDateDateTimeLayout))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinDate_toISOString(call FunctionCall) Value {
|
func builtinDateToISOString(call FunctionCall) Value {
|
||||||
date := dateObjectOf(call.runtime, call.thisObject())
|
date := dateObjectOf(call.runtime, call.thisObject())
|
||||||
if date.isNaN {
|
if date.isNaN {
|
||||||
return toValue_string("Invalid Date")
|
return stringValue("Invalid Date")
|
||||||
}
|
}
|
||||||
return toValue_string(date.Time().Format("2006-01-02T15:04:05.000Z"))
|
return stringValue(date.Time().Format("2006-01-02T15:04:05.000Z"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinDate_toJSON(call FunctionCall) Value {
|
func builtinDateToJSON(call FunctionCall) Value {
|
||||||
object := call.thisObject()
|
obj := call.thisObject()
|
||||||
value := object.DefaultValue(defaultValueHintNumber) // FIXME object.primitiveNumberValue
|
value := obj.DefaultValue(defaultValueHintNumber) // FIXME object.primitiveNumberValue
|
||||||
{ // FIXME value.isFinite
|
// FIXME fv.isFinite
|
||||||
value := value.float64()
|
if fv := value.float64(); math.IsNaN(fv) || math.IsInf(fv, 0) {
|
||||||
if math.IsNaN(value) || math.IsInf(value, 0) {
|
|
||||||
return nullValue
|
return nullValue
|
||||||
}
|
}
|
||||||
}
|
|
||||||
toISOString := object.get("toISOString")
|
toISOString := obj.get("toISOString")
|
||||||
if !toISOString.isCallable() {
|
if !toISOString.isCallable() {
|
||||||
// FIXME
|
// FIXME
|
||||||
panic(call.runtime.panicTypeError())
|
panic(call.runtime.panicTypeError("Date.toJSON toISOString %q is not callable", toISOString))
|
||||||
}
|
}
|
||||||
return toISOString.call(call.runtime, toValue_object(object), []Value{})
|
return toISOString.call(call.runtime, objectValue(obj), []Value{})
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinDate_toGMTString(call FunctionCall) Value {
|
func builtinDateToGMTString(call FunctionCall) Value {
|
||||||
date := dateObjectOf(call.runtime, call.thisObject())
|
date := dateObjectOf(call.runtime, call.thisObject())
|
||||||
if date.isNaN {
|
if date.isNaN {
|
||||||
return toValue_string("Invalid Date")
|
return stringValue("Invalid Date")
|
||||||
}
|
}
|
||||||
return toValue_string(date.Time().Format("Mon, 02 Jan 2006 15:04:05 GMT"))
|
return stringValue(date.Time().Format("Mon, 02 Jan 2006 15:04:05 GMT"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinDate_getTime(call FunctionCall) Value {
|
func builtinDateGetTime(call FunctionCall) Value {
|
||||||
date := dateObjectOf(call.runtime, call.thisObject())
|
date := dateObjectOf(call.runtime, call.thisObject())
|
||||||
if date.isNaN {
|
if date.isNaN {
|
||||||
return NaNValue()
|
return NaNValue()
|
||||||
}
|
}
|
||||||
// We do this (convert away from a float) so the user
|
// We do this (convert away from a float) so the user
|
||||||
// does not get something back in exponential notation
|
// does not get something back in exponential notation
|
||||||
return toValue_int64(int64(date.Epoch()))
|
return int64Value(date.Epoch())
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinDate_setTime(call FunctionCall) Value {
|
func builtinDateSetTime(call FunctionCall) Value {
|
||||||
object := call.thisObject()
|
obj := call.thisObject()
|
||||||
date := dateObjectOf(call.runtime, call.thisObject())
|
date := dateObjectOf(call.runtime, call.thisObject())
|
||||||
date.Set(call.Argument(0).float64())
|
date.Set(call.Argument(0).float64())
|
||||||
object.value = date
|
obj.value = date
|
||||||
return date.Value()
|
return date.Value()
|
||||||
}
|
}
|
||||||
|
|
||||||
func _builtinDate_beforeSet(call FunctionCall, argumentLimit int, timeLocal bool) (*_object, *_dateObject, *_ecmaTime, []int) {
|
func builtinDateBeforeSet(call FunctionCall, argumentLimit int, timeLocal bool) (*object, *dateObject, *ecmaTime, []int) {
|
||||||
object := call.thisObject()
|
obj := call.thisObject()
|
||||||
date := dateObjectOf(call.runtime, call.thisObject())
|
date := dateObjectOf(call.runtime, call.thisObject())
|
||||||
if date.isNaN {
|
if date.isNaN {
|
||||||
return nil, nil, nil, nil
|
return nil, nil, nil, nil
|
||||||
|
@ -127,7 +124,7 @@ func _builtinDate_beforeSet(call FunctionCall, argumentLimit int, timeLocal bool
|
||||||
}
|
}
|
||||||
|
|
||||||
if argumentLimit == 0 {
|
if argumentLimit == 0 {
|
||||||
object.value = invalidDateObject
|
obj.value = invalidDateObject
|
||||||
return nil, nil, nil, nil
|
return nil, nil, nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,61 +135,61 @@ func _builtinDate_beforeSet(call FunctionCall, argumentLimit int, timeLocal bool
|
||||||
switch nm.kind {
|
switch nm.kind {
|
||||||
case numberInteger, numberFloat:
|
case numberInteger, numberFloat:
|
||||||
default:
|
default:
|
||||||
object.value = invalidDateObject
|
obj.value = invalidDateObject
|
||||||
return nil, nil, nil, nil
|
return nil, nil, nil, nil
|
||||||
}
|
}
|
||||||
valueList[index] = int(nm.int64)
|
valueList[index] = int(nm.int64)
|
||||||
}
|
}
|
||||||
baseTime := date.Time()
|
baseTime := date.Time()
|
||||||
if timeLocal {
|
if timeLocal {
|
||||||
baseTime = baseTime.Local()
|
baseTime = baseTime.Local() //nolint: gosmopolitan
|
||||||
}
|
}
|
||||||
ecmaTime := ecmaTime(baseTime)
|
ecmaTime := newEcmaTime(baseTime)
|
||||||
return object, &date, &ecmaTime, valueList
|
return obj, &date, &ecmaTime, valueList
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinDate_parse(call FunctionCall) Value {
|
func builtinDateParse(call FunctionCall) Value {
|
||||||
date := call.Argument(0).string()
|
date := call.Argument(0).string()
|
||||||
return toValue_float64(dateParse(date))
|
return float64Value(dateParse(date))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinDate_UTC(call FunctionCall) Value {
|
func builtinDateUTC(call FunctionCall) Value {
|
||||||
return toValue_float64(newDateTime(call.ArgumentList, Time.UTC))
|
return float64Value(newDateTime(call.ArgumentList, time.UTC))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinDate_now(call FunctionCall) Value {
|
func builtinDateNow(call FunctionCall) Value {
|
||||||
call.ArgumentList = []Value(nil)
|
call.ArgumentList = []Value(nil)
|
||||||
return builtinDate_UTC(call)
|
return builtinDateUTC(call)
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is a placeholder
|
// This is a placeholder.
|
||||||
func builtinDate_toLocaleString(call FunctionCall) Value {
|
func builtinDateToLocaleString(call FunctionCall) Value {
|
||||||
date := dateObjectOf(call.runtime, call.thisObject())
|
date := dateObjectOf(call.runtime, call.thisObject())
|
||||||
if date.isNaN {
|
if date.isNaN {
|
||||||
return toValue_string("Invalid Date")
|
return stringValue("Invalid Date")
|
||||||
}
|
}
|
||||||
return toValue_string(date.Time().Local().Format("2006-01-02 15:04:05"))
|
return stringValue(date.Time().Local().Format("2006-01-02 15:04:05")) //nolint: gosmopolitan
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is a placeholder
|
// This is a placeholder.
|
||||||
func builtinDate_toLocaleDateString(call FunctionCall) Value {
|
func builtinDateToLocaleDateString(call FunctionCall) Value {
|
||||||
date := dateObjectOf(call.runtime, call.thisObject())
|
date := dateObjectOf(call.runtime, call.thisObject())
|
||||||
if date.isNaN {
|
if date.isNaN {
|
||||||
return toValue_string("Invalid Date")
|
return stringValue("Invalid Date")
|
||||||
}
|
}
|
||||||
return toValue_string(date.Time().Local().Format("2006-01-02"))
|
return stringValue(date.Time().Local().Format("2006-01-02")) //nolint: gosmopolitan
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is a placeholder
|
// This is a placeholder.
|
||||||
func builtinDate_toLocaleTimeString(call FunctionCall) Value {
|
func builtinDateToLocaleTimeString(call FunctionCall) Value {
|
||||||
date := dateObjectOf(call.runtime, call.thisObject())
|
date := dateObjectOf(call.runtime, call.thisObject())
|
||||||
if date.isNaN {
|
if date.isNaN {
|
||||||
return toValue_string("Invalid Date")
|
return stringValue("Invalid Date")
|
||||||
}
|
}
|
||||||
return toValue_string(date.Time().Local().Format("15:04:05"))
|
return stringValue(date.Time().Local().Format("15:04:05")) //nolint: gosmopolitan
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinDate_valueOf(call FunctionCall) Value {
|
func builtinDateValueOf(call FunctionCall) Value {
|
||||||
date := dateObjectOf(call.runtime, call.thisObject())
|
date := dateObjectOf(call.runtime, call.thisObject())
|
||||||
if date.isNaN {
|
if date.isNaN {
|
||||||
return NaNValue()
|
return NaNValue()
|
||||||
|
@ -200,155 +197,155 @@ func builtinDate_valueOf(call FunctionCall) Value {
|
||||||
return date.Value()
|
return date.Value()
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinDate_getYear(call FunctionCall) Value {
|
func builtinDateGetYear(call FunctionCall) Value {
|
||||||
// Will throw a TypeError is ThisObject is nil or
|
// Will throw a TypeError is ThisObject is nil or
|
||||||
// does not have Class of "Date"
|
// does not have Class of "Date"
|
||||||
date := dateObjectOf(call.runtime, call.thisObject())
|
date := dateObjectOf(call.runtime, call.thisObject())
|
||||||
if date.isNaN {
|
if date.isNaN {
|
||||||
return NaNValue()
|
return NaNValue()
|
||||||
}
|
}
|
||||||
return toValue_int(date.Time().Local().Year() - 1900)
|
return intValue(date.Time().Local().Year() - 1900) //nolint: gosmopolitan
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinDate_getFullYear(call FunctionCall) Value {
|
func builtinDateGetFullYear(call FunctionCall) Value {
|
||||||
// Will throw a TypeError is ThisObject is nil or
|
// Will throw a TypeError is ThisObject is nil or
|
||||||
// does not have Class of "Date"
|
// does not have Class of "Date"
|
||||||
date := dateObjectOf(call.runtime, call.thisObject())
|
date := dateObjectOf(call.runtime, call.thisObject())
|
||||||
if date.isNaN {
|
if date.isNaN {
|
||||||
return NaNValue()
|
return NaNValue()
|
||||||
}
|
}
|
||||||
return toValue_int(date.Time().Local().Year())
|
return intValue(date.Time().Local().Year()) //nolint: gosmopolitan
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinDate_getUTCFullYear(call FunctionCall) Value {
|
func builtinDateGetUTCFullYear(call FunctionCall) Value {
|
||||||
date := dateObjectOf(call.runtime, call.thisObject())
|
date := dateObjectOf(call.runtime, call.thisObject())
|
||||||
if date.isNaN {
|
if date.isNaN {
|
||||||
return NaNValue()
|
return NaNValue()
|
||||||
}
|
}
|
||||||
return toValue_int(date.Time().Year())
|
return intValue(date.Time().Year())
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinDate_getMonth(call FunctionCall) Value {
|
func builtinDateGetMonth(call FunctionCall) Value {
|
||||||
date := dateObjectOf(call.runtime, call.thisObject())
|
date := dateObjectOf(call.runtime, call.thisObject())
|
||||||
if date.isNaN {
|
if date.isNaN {
|
||||||
return NaNValue()
|
return NaNValue()
|
||||||
}
|
}
|
||||||
return toValue_int(dateFromGoMonth(date.Time().Local().Month()))
|
return intValue(dateFromGoMonth(date.Time().Local().Month())) //nolint: gosmopolitan
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinDate_getUTCMonth(call FunctionCall) Value {
|
func builtinDateGetUTCMonth(call FunctionCall) Value {
|
||||||
date := dateObjectOf(call.runtime, call.thisObject())
|
date := dateObjectOf(call.runtime, call.thisObject())
|
||||||
if date.isNaN {
|
if date.isNaN {
|
||||||
return NaNValue()
|
return NaNValue()
|
||||||
}
|
}
|
||||||
return toValue_int(dateFromGoMonth(date.Time().Month()))
|
return intValue(dateFromGoMonth(date.Time().Month()))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinDate_getDate(call FunctionCall) Value {
|
func builtinDateGetDate(call FunctionCall) Value {
|
||||||
date := dateObjectOf(call.runtime, call.thisObject())
|
date := dateObjectOf(call.runtime, call.thisObject())
|
||||||
if date.isNaN {
|
if date.isNaN {
|
||||||
return NaNValue()
|
return NaNValue()
|
||||||
}
|
}
|
||||||
return toValue_int(date.Time().Local().Day())
|
return intValue(date.Time().Local().Day()) //nolint: gosmopolitan
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinDate_getUTCDate(call FunctionCall) Value {
|
func builtinDateGetUTCDate(call FunctionCall) Value {
|
||||||
date := dateObjectOf(call.runtime, call.thisObject())
|
date := dateObjectOf(call.runtime, call.thisObject())
|
||||||
if date.isNaN {
|
if date.isNaN {
|
||||||
return NaNValue()
|
return NaNValue()
|
||||||
}
|
}
|
||||||
return toValue_int(date.Time().Day())
|
return intValue(date.Time().Day())
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinDate_getDay(call FunctionCall) Value {
|
func builtinDateGetDay(call FunctionCall) Value {
|
||||||
// Actually day of the week
|
// Actually day of the week
|
||||||
date := dateObjectOf(call.runtime, call.thisObject())
|
date := dateObjectOf(call.runtime, call.thisObject())
|
||||||
if date.isNaN {
|
if date.isNaN {
|
||||||
return NaNValue()
|
return NaNValue()
|
||||||
}
|
}
|
||||||
return toValue_int(dateFromGoDay(date.Time().Local().Weekday()))
|
return intValue(dateFromGoDay(date.Time().Local().Weekday())) //nolint: gosmopolitan
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinDate_getUTCDay(call FunctionCall) Value {
|
func builtinDateGetUTCDay(call FunctionCall) Value {
|
||||||
date := dateObjectOf(call.runtime, call.thisObject())
|
date := dateObjectOf(call.runtime, call.thisObject())
|
||||||
if date.isNaN {
|
if date.isNaN {
|
||||||
return NaNValue()
|
return NaNValue()
|
||||||
}
|
}
|
||||||
return toValue_int(dateFromGoDay(date.Time().Weekday()))
|
return intValue(dateFromGoDay(date.Time().Weekday()))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinDate_getHours(call FunctionCall) Value {
|
func builtinDateGetHours(call FunctionCall) Value {
|
||||||
date := dateObjectOf(call.runtime, call.thisObject())
|
date := dateObjectOf(call.runtime, call.thisObject())
|
||||||
if date.isNaN {
|
if date.isNaN {
|
||||||
return NaNValue()
|
return NaNValue()
|
||||||
}
|
}
|
||||||
return toValue_int(date.Time().Local().Hour())
|
return intValue(date.Time().Local().Hour()) //nolint: gosmopolitan
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinDate_getUTCHours(call FunctionCall) Value {
|
func builtinDateGetUTCHours(call FunctionCall) Value {
|
||||||
date := dateObjectOf(call.runtime, call.thisObject())
|
date := dateObjectOf(call.runtime, call.thisObject())
|
||||||
if date.isNaN {
|
if date.isNaN {
|
||||||
return NaNValue()
|
return NaNValue()
|
||||||
}
|
}
|
||||||
return toValue_int(date.Time().Hour())
|
return intValue(date.Time().Hour())
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinDate_getMinutes(call FunctionCall) Value {
|
func builtinDateGetMinutes(call FunctionCall) Value {
|
||||||
date := dateObjectOf(call.runtime, call.thisObject())
|
date := dateObjectOf(call.runtime, call.thisObject())
|
||||||
if date.isNaN {
|
if date.isNaN {
|
||||||
return NaNValue()
|
return NaNValue()
|
||||||
}
|
}
|
||||||
return toValue_int(date.Time().Local().Minute())
|
return intValue(date.Time().Local().Minute()) //nolint: gosmopolitan
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinDate_getUTCMinutes(call FunctionCall) Value {
|
func builtinDateGetUTCMinutes(call FunctionCall) Value {
|
||||||
date := dateObjectOf(call.runtime, call.thisObject())
|
date := dateObjectOf(call.runtime, call.thisObject())
|
||||||
if date.isNaN {
|
if date.isNaN {
|
||||||
return NaNValue()
|
return NaNValue()
|
||||||
}
|
}
|
||||||
return toValue_int(date.Time().Minute())
|
return intValue(date.Time().Minute())
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinDate_getSeconds(call FunctionCall) Value {
|
func builtinDateGetSeconds(call FunctionCall) Value {
|
||||||
date := dateObjectOf(call.runtime, call.thisObject())
|
date := dateObjectOf(call.runtime, call.thisObject())
|
||||||
if date.isNaN {
|
if date.isNaN {
|
||||||
return NaNValue()
|
return NaNValue()
|
||||||
}
|
}
|
||||||
return toValue_int(date.Time().Local().Second())
|
return intValue(date.Time().Local().Second()) //nolint: gosmopolitan
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinDate_getUTCSeconds(call FunctionCall) Value {
|
func builtinDateGetUTCSeconds(call FunctionCall) Value {
|
||||||
date := dateObjectOf(call.runtime, call.thisObject())
|
date := dateObjectOf(call.runtime, call.thisObject())
|
||||||
if date.isNaN {
|
if date.isNaN {
|
||||||
return NaNValue()
|
return NaNValue()
|
||||||
}
|
}
|
||||||
return toValue_int(date.Time().Second())
|
return intValue(date.Time().Second())
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinDate_getMilliseconds(call FunctionCall) Value {
|
func builtinDateGetMilliseconds(call FunctionCall) Value {
|
||||||
date := dateObjectOf(call.runtime, call.thisObject())
|
date := dateObjectOf(call.runtime, call.thisObject())
|
||||||
if date.isNaN {
|
if date.isNaN {
|
||||||
return NaNValue()
|
return NaNValue()
|
||||||
}
|
}
|
||||||
return toValue_int(date.Time().Local().Nanosecond() / (100 * 100 * 100))
|
return intValue(date.Time().Local().Nanosecond() / (100 * 100 * 100)) //nolint: gosmopolitan
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinDate_getUTCMilliseconds(call FunctionCall) Value {
|
func builtinDateGetUTCMilliseconds(call FunctionCall) Value {
|
||||||
date := dateObjectOf(call.runtime, call.thisObject())
|
date := dateObjectOf(call.runtime, call.thisObject())
|
||||||
if date.isNaN {
|
if date.isNaN {
|
||||||
return NaNValue()
|
return NaNValue()
|
||||||
}
|
}
|
||||||
return toValue_int(date.Time().Nanosecond() / (100 * 100 * 100))
|
return intValue(date.Time().Nanosecond() / (100 * 100 * 100))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinDate_getTimezoneOffset(call FunctionCall) Value {
|
func builtinDateGetTimezoneOffset(call FunctionCall) Value {
|
||||||
date := dateObjectOf(call.runtime, call.thisObject())
|
date := dateObjectOf(call.runtime, call.thisObject())
|
||||||
if date.isNaN {
|
if date.isNaN {
|
||||||
return NaNValue()
|
return NaNValue()
|
||||||
}
|
}
|
||||||
timeLocal := date.Time().Local()
|
timeLocal := date.Time().Local() //nolint: gosmopolitan
|
||||||
// Is this kosher?
|
// Is this kosher?
|
||||||
timeLocalAsUTC := Time.Date(
|
timeLocalAsUTC := time.Date(
|
||||||
timeLocal.Year(),
|
timeLocal.Year(),
|
||||||
timeLocal.Month(),
|
timeLocal.Month(),
|
||||||
timeLocal.Day(),
|
timeLocal.Day(),
|
||||||
|
@ -356,13 +353,13 @@ func builtinDate_getTimezoneOffset(call FunctionCall) Value {
|
||||||
timeLocal.Minute(),
|
timeLocal.Minute(),
|
||||||
timeLocal.Second(),
|
timeLocal.Second(),
|
||||||
timeLocal.Nanosecond(),
|
timeLocal.Nanosecond(),
|
||||||
Time.UTC,
|
time.UTC,
|
||||||
)
|
)
|
||||||
return toValue_float64(date.Time().Sub(timeLocalAsUTC).Seconds() / 60)
|
return float64Value(date.Time().Sub(timeLocalAsUTC).Seconds() / 60)
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinDate_setMilliseconds(call FunctionCall) Value {
|
func builtinDateSetMilliseconds(call FunctionCall) Value {
|
||||||
object, date, ecmaTime, value := _builtinDate_beforeSet(call, 1, true)
|
obj, date, ecmaTime, value := builtinDateBeforeSet(call, 1, true)
|
||||||
if ecmaTime == nil {
|
if ecmaTime == nil {
|
||||||
return NaNValue()
|
return NaNValue()
|
||||||
}
|
}
|
||||||
|
@ -370,12 +367,12 @@ func builtinDate_setMilliseconds(call FunctionCall) Value {
|
||||||
ecmaTime.millisecond = value[0]
|
ecmaTime.millisecond = value[0]
|
||||||
|
|
||||||
date.SetTime(ecmaTime.goTime())
|
date.SetTime(ecmaTime.goTime())
|
||||||
object.value = *date
|
obj.value = *date
|
||||||
return date.Value()
|
return date.Value()
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinDate_setUTCMilliseconds(call FunctionCall) Value {
|
func builtinDateSetUTCMilliseconds(call FunctionCall) Value {
|
||||||
object, date, ecmaTime, value := _builtinDate_beforeSet(call, 1, false)
|
obj, date, ecmaTime, value := builtinDateBeforeSet(call, 1, false)
|
||||||
if ecmaTime == nil {
|
if ecmaTime == nil {
|
||||||
return NaNValue()
|
return NaNValue()
|
||||||
}
|
}
|
||||||
|
@ -383,12 +380,12 @@ func builtinDate_setUTCMilliseconds(call FunctionCall) Value {
|
||||||
ecmaTime.millisecond = value[0]
|
ecmaTime.millisecond = value[0]
|
||||||
|
|
||||||
date.SetTime(ecmaTime.goTime())
|
date.SetTime(ecmaTime.goTime())
|
||||||
object.value = *date
|
obj.value = *date
|
||||||
return date.Value()
|
return date.Value()
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinDate_setSeconds(call FunctionCall) Value {
|
func builtinDateSetSeconds(call FunctionCall) Value {
|
||||||
object, date, ecmaTime, value := _builtinDate_beforeSet(call, 2, true)
|
obj, date, ecmaTime, value := builtinDateBeforeSet(call, 2, true)
|
||||||
if ecmaTime == nil {
|
if ecmaTime == nil {
|
||||||
return NaNValue()
|
return NaNValue()
|
||||||
}
|
}
|
||||||
|
@ -399,12 +396,12 @@ func builtinDate_setSeconds(call FunctionCall) Value {
|
||||||
ecmaTime.second = value[0]
|
ecmaTime.second = value[0]
|
||||||
|
|
||||||
date.SetTime(ecmaTime.goTime())
|
date.SetTime(ecmaTime.goTime())
|
||||||
object.value = *date
|
obj.value = *date
|
||||||
return date.Value()
|
return date.Value()
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinDate_setUTCSeconds(call FunctionCall) Value {
|
func builtinDateSetUTCSeconds(call FunctionCall) Value {
|
||||||
object, date, ecmaTime, value := _builtinDate_beforeSet(call, 2, false)
|
obj, date, ecmaTime, value := builtinDateBeforeSet(call, 2, false)
|
||||||
if ecmaTime == nil {
|
if ecmaTime == nil {
|
||||||
return NaNValue()
|
return NaNValue()
|
||||||
}
|
}
|
||||||
|
@ -415,12 +412,12 @@ func builtinDate_setUTCSeconds(call FunctionCall) Value {
|
||||||
ecmaTime.second = value[0]
|
ecmaTime.second = value[0]
|
||||||
|
|
||||||
date.SetTime(ecmaTime.goTime())
|
date.SetTime(ecmaTime.goTime())
|
||||||
object.value = *date
|
obj.value = *date
|
||||||
return date.Value()
|
return date.Value()
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinDate_setMinutes(call FunctionCall) Value {
|
func builtinDateSetMinutes(call FunctionCall) Value {
|
||||||
object, date, ecmaTime, value := _builtinDate_beforeSet(call, 3, true)
|
obj, date, ecmaTime, value := builtinDateBeforeSet(call, 3, true)
|
||||||
if ecmaTime == nil {
|
if ecmaTime == nil {
|
||||||
return NaNValue()
|
return NaNValue()
|
||||||
}
|
}
|
||||||
|
@ -434,12 +431,12 @@ func builtinDate_setMinutes(call FunctionCall) Value {
|
||||||
ecmaTime.minute = value[0]
|
ecmaTime.minute = value[0]
|
||||||
|
|
||||||
date.SetTime(ecmaTime.goTime())
|
date.SetTime(ecmaTime.goTime())
|
||||||
object.value = *date
|
obj.value = *date
|
||||||
return date.Value()
|
return date.Value()
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinDate_setUTCMinutes(call FunctionCall) Value {
|
func builtinDateSetUTCMinutes(call FunctionCall) Value {
|
||||||
object, date, ecmaTime, value := _builtinDate_beforeSet(call, 3, false)
|
obj, date, ecmaTime, value := builtinDateBeforeSet(call, 3, false)
|
||||||
if ecmaTime == nil {
|
if ecmaTime == nil {
|
||||||
return NaNValue()
|
return NaNValue()
|
||||||
}
|
}
|
||||||
|
@ -453,58 +450,58 @@ func builtinDate_setUTCMinutes(call FunctionCall) Value {
|
||||||
ecmaTime.minute = value[0]
|
ecmaTime.minute = value[0]
|
||||||
|
|
||||||
date.SetTime(ecmaTime.goTime())
|
date.SetTime(ecmaTime.goTime())
|
||||||
object.value = *date
|
obj.value = *date
|
||||||
return date.Value()
|
return date.Value()
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinDate_setHours(call FunctionCall) Value {
|
func builtinDateSetHours(call FunctionCall) Value {
|
||||||
object, date, ecmaTime, value := _builtinDate_beforeSet(call, 4, true)
|
obj, date, ecmaTime, value := builtinDateBeforeSet(call, 4, true)
|
||||||
if ecmaTime == nil {
|
if ecmaTime == nil {
|
||||||
return NaNValue()
|
return NaNValue()
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(value) > 3 {
|
switch {
|
||||||
|
case len(value) > 3:
|
||||||
ecmaTime.millisecond = value[3]
|
ecmaTime.millisecond = value[3]
|
||||||
|
fallthrough
|
||||||
|
case len(value) > 2:
|
||||||
ecmaTime.second = value[2]
|
ecmaTime.second = value[2]
|
||||||
ecmaTime.minute = value[1]
|
fallthrough
|
||||||
} else if len(value) > 2 {
|
case len(value) > 1:
|
||||||
ecmaTime.second = value[2]
|
|
||||||
ecmaTime.minute = value[1]
|
|
||||||
} else if len(value) > 1 {
|
|
||||||
ecmaTime.minute = value[1]
|
ecmaTime.minute = value[1]
|
||||||
}
|
}
|
||||||
ecmaTime.hour = value[0]
|
ecmaTime.hour = value[0]
|
||||||
|
|
||||||
date.SetTime(ecmaTime.goTime())
|
date.SetTime(ecmaTime.goTime())
|
||||||
object.value = *date
|
obj.value = *date
|
||||||
return date.Value()
|
return date.Value()
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinDate_setUTCHours(call FunctionCall) Value {
|
func builtinDateSetUTCHours(call FunctionCall) Value {
|
||||||
object, date, ecmaTime, value := _builtinDate_beforeSet(call, 4, false)
|
obj, date, ecmaTime, value := builtinDateBeforeSet(call, 4, false)
|
||||||
if ecmaTime == nil {
|
if ecmaTime == nil {
|
||||||
return NaNValue()
|
return NaNValue()
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(value) > 3 {
|
switch {
|
||||||
|
case len(value) > 3:
|
||||||
ecmaTime.millisecond = value[3]
|
ecmaTime.millisecond = value[3]
|
||||||
|
fallthrough
|
||||||
|
case len(value) > 2:
|
||||||
ecmaTime.second = value[2]
|
ecmaTime.second = value[2]
|
||||||
ecmaTime.minute = value[1]
|
fallthrough
|
||||||
} else if len(value) > 2 {
|
case len(value) > 1:
|
||||||
ecmaTime.second = value[2]
|
|
||||||
ecmaTime.minute = value[1]
|
|
||||||
} else if len(value) > 1 {
|
|
||||||
ecmaTime.minute = value[1]
|
ecmaTime.minute = value[1]
|
||||||
}
|
}
|
||||||
ecmaTime.hour = value[0]
|
ecmaTime.hour = value[0]
|
||||||
|
|
||||||
date.SetTime(ecmaTime.goTime())
|
date.SetTime(ecmaTime.goTime())
|
||||||
object.value = *date
|
obj.value = *date
|
||||||
return date.Value()
|
return date.Value()
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinDate_setDate(call FunctionCall) Value {
|
func builtinDateSetDate(call FunctionCall) Value {
|
||||||
object, date, ecmaTime, value := _builtinDate_beforeSet(call, 1, true)
|
obj, date, ecmaTime, value := builtinDateBeforeSet(call, 1, true)
|
||||||
if ecmaTime == nil {
|
if ecmaTime == nil {
|
||||||
return NaNValue()
|
return NaNValue()
|
||||||
}
|
}
|
||||||
|
@ -512,12 +509,12 @@ func builtinDate_setDate(call FunctionCall) Value {
|
||||||
ecmaTime.day = value[0]
|
ecmaTime.day = value[0]
|
||||||
|
|
||||||
date.SetTime(ecmaTime.goTime())
|
date.SetTime(ecmaTime.goTime())
|
||||||
object.value = *date
|
obj.value = *date
|
||||||
return date.Value()
|
return date.Value()
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinDate_setUTCDate(call FunctionCall) Value {
|
func builtinDateSetUTCDate(call FunctionCall) Value {
|
||||||
object, date, ecmaTime, value := _builtinDate_beforeSet(call, 1, false)
|
obj, date, ecmaTime, value := builtinDateBeforeSet(call, 1, false)
|
||||||
if ecmaTime == nil {
|
if ecmaTime == nil {
|
||||||
return NaNValue()
|
return NaNValue()
|
||||||
}
|
}
|
||||||
|
@ -525,12 +522,12 @@ func builtinDate_setUTCDate(call FunctionCall) Value {
|
||||||
ecmaTime.day = value[0]
|
ecmaTime.day = value[0]
|
||||||
|
|
||||||
date.SetTime(ecmaTime.goTime())
|
date.SetTime(ecmaTime.goTime())
|
||||||
object.value = *date
|
obj.value = *date
|
||||||
return date.Value()
|
return date.Value()
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinDate_setMonth(call FunctionCall) Value {
|
func builtinDateSetMonth(call FunctionCall) Value {
|
||||||
object, date, ecmaTime, value := _builtinDate_beforeSet(call, 2, true)
|
obj, date, ecmaTime, value := builtinDateBeforeSet(call, 2, true)
|
||||||
if ecmaTime == nil {
|
if ecmaTime == nil {
|
||||||
return NaNValue()
|
return NaNValue()
|
||||||
}
|
}
|
||||||
|
@ -541,12 +538,12 @@ func builtinDate_setMonth(call FunctionCall) Value {
|
||||||
ecmaTime.month = value[0]
|
ecmaTime.month = value[0]
|
||||||
|
|
||||||
date.SetTime(ecmaTime.goTime())
|
date.SetTime(ecmaTime.goTime())
|
||||||
object.value = *date
|
obj.value = *date
|
||||||
return date.Value()
|
return date.Value()
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinDate_setUTCMonth(call FunctionCall) Value {
|
func builtinDateSetUTCMonth(call FunctionCall) Value {
|
||||||
object, date, ecmaTime, value := _builtinDate_beforeSet(call, 2, false)
|
obj, date, ecmaTime, value := builtinDateBeforeSet(call, 2, false)
|
||||||
if ecmaTime == nil {
|
if ecmaTime == nil {
|
||||||
return NaNValue()
|
return NaNValue()
|
||||||
}
|
}
|
||||||
|
@ -557,12 +554,12 @@ func builtinDate_setUTCMonth(call FunctionCall) Value {
|
||||||
ecmaTime.month = value[0]
|
ecmaTime.month = value[0]
|
||||||
|
|
||||||
date.SetTime(ecmaTime.goTime())
|
date.SetTime(ecmaTime.goTime())
|
||||||
object.value = *date
|
obj.value = *date
|
||||||
return date.Value()
|
return date.Value()
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinDate_setYear(call FunctionCall) Value {
|
func builtinDateSetYear(call FunctionCall) Value {
|
||||||
object, date, ecmaTime, value := _builtinDate_beforeSet(call, 1, true)
|
obj, date, ecmaTime, value := builtinDateBeforeSet(call, 1, true)
|
||||||
if ecmaTime == nil {
|
if ecmaTime == nil {
|
||||||
return NaNValue()
|
return NaNValue()
|
||||||
}
|
}
|
||||||
|
@ -574,12 +571,12 @@ func builtinDate_setYear(call FunctionCall) Value {
|
||||||
ecmaTime.year = year
|
ecmaTime.year = year
|
||||||
|
|
||||||
date.SetTime(ecmaTime.goTime())
|
date.SetTime(ecmaTime.goTime())
|
||||||
object.value = *date
|
obj.value = *date
|
||||||
return date.Value()
|
return date.Value()
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinDate_setFullYear(call FunctionCall) Value {
|
func builtinDateSetFullYear(call FunctionCall) Value {
|
||||||
object, date, ecmaTime, value := _builtinDate_beforeSet(call, 3, true)
|
obj, date, ecmaTime, value := builtinDateBeforeSet(call, 3, true)
|
||||||
if ecmaTime == nil {
|
if ecmaTime == nil {
|
||||||
return NaNValue()
|
return NaNValue()
|
||||||
}
|
}
|
||||||
|
@ -593,12 +590,12 @@ func builtinDate_setFullYear(call FunctionCall) Value {
|
||||||
ecmaTime.year = value[0]
|
ecmaTime.year = value[0]
|
||||||
|
|
||||||
date.SetTime(ecmaTime.goTime())
|
date.SetTime(ecmaTime.goTime())
|
||||||
object.value = *date
|
obj.value = *date
|
||||||
return date.Value()
|
return date.Value()
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinDate_setUTCFullYear(call FunctionCall) Value {
|
func builtinDateSetUTCFullYear(call FunctionCall) Value {
|
||||||
object, date, ecmaTime, value := _builtinDate_beforeSet(call, 3, false)
|
obj, date, ecmaTime, value := builtinDateBeforeSet(call, 3, false)
|
||||||
if ecmaTime == nil {
|
if ecmaTime == nil {
|
||||||
return NaNValue()
|
return NaNValue()
|
||||||
}
|
}
|
||||||
|
@ -612,7 +609,7 @@ func builtinDate_setUTCFullYear(call FunctionCall) Value {
|
||||||
ecmaTime.year = value[0]
|
ecmaTime.year = value[0]
|
||||||
|
|
||||||
date.SetTime(ecmaTime.goTime())
|
date.SetTime(ecmaTime.goTime())
|
||||||
object.value = *date
|
obj.value = *date
|
||||||
return date.Value()
|
return date.Value()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
102
v1/vendor/github.com/robertkrimen/otto/builtin_error.go
generated
vendored
|
@ -5,20 +5,20 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func builtinError(call FunctionCall) Value {
|
func builtinError(call FunctionCall) Value {
|
||||||
return toValue_object(call.runtime.newError(classError, call.Argument(0), 1))
|
return objectValue(call.runtime.newError(classErrorName, call.Argument(0), 1))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinNewError(self *_object, argumentList []Value) Value {
|
func builtinNewError(obj *object, argumentList []Value) Value {
|
||||||
return toValue_object(self.runtime.newError(classError, valueOfArrayIndex(argumentList, 0), 0))
|
return objectValue(obj.runtime.newError(classErrorName, valueOfArrayIndex(argumentList, 0), 0))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinError_toString(call FunctionCall) Value {
|
func builtinErrorToString(call FunctionCall) Value {
|
||||||
thisObject := call.thisObject()
|
thisObject := call.thisObject()
|
||||||
if thisObject == nil {
|
if thisObject == nil {
|
||||||
panic(call.runtime.panicTypeError())
|
panic(call.runtime.panicTypeError("Error.toString is nil"))
|
||||||
}
|
}
|
||||||
|
|
||||||
name := classError
|
name := classErrorName
|
||||||
nameValue := thisObject.get("name")
|
nameValue := thisObject.get("name")
|
||||||
if nameValue.IsDefined() {
|
if nameValue.IsDefined() {
|
||||||
name = nameValue.string()
|
name = nameValue.string()
|
||||||
|
@ -31,96 +31,96 @@ func builtinError_toString(call FunctionCall) Value {
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(name) == 0 {
|
if len(name) == 0 {
|
||||||
return toValue_string(message)
|
return stringValue(message)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(message) == 0 {
|
if len(message) == 0 {
|
||||||
return toValue_string(name)
|
return stringValue(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
return toValue_string(fmt.Sprintf("%s: %s", name, message))
|
return stringValue(fmt.Sprintf("%s: %s", name, message))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (runtime *_runtime) newEvalError(message Value) *_object {
|
func (rt *runtime) newEvalError(message Value) *object {
|
||||||
self := runtime.newErrorObject("EvalError", message, 0)
|
o := rt.newErrorObject("EvalError", message, 0)
|
||||||
self.prototype = runtime.global.EvalErrorPrototype
|
o.prototype = rt.global.EvalErrorPrototype
|
||||||
return self
|
return o
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinEvalError(call FunctionCall) Value {
|
func builtinEvalError(call FunctionCall) Value {
|
||||||
return toValue_object(call.runtime.newEvalError(call.Argument(0)))
|
return objectValue(call.runtime.newEvalError(call.Argument(0)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinNewEvalError(self *_object, argumentList []Value) Value {
|
func builtinNewEvalError(obj *object, argumentList []Value) Value {
|
||||||
return toValue_object(self.runtime.newEvalError(valueOfArrayIndex(argumentList, 0)))
|
return objectValue(obj.runtime.newEvalError(valueOfArrayIndex(argumentList, 0)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (runtime *_runtime) newTypeError(message Value) *_object {
|
func (rt *runtime) newTypeError(message Value) *object {
|
||||||
self := runtime.newErrorObject("TypeError", message, 0)
|
o := rt.newErrorObject("TypeError", message, 0)
|
||||||
self.prototype = runtime.global.TypeErrorPrototype
|
o.prototype = rt.global.TypeErrorPrototype
|
||||||
return self
|
return o
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinTypeError(call FunctionCall) Value {
|
func builtinTypeError(call FunctionCall) Value {
|
||||||
return toValue_object(call.runtime.newTypeError(call.Argument(0)))
|
return objectValue(call.runtime.newTypeError(call.Argument(0)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinNewTypeError(self *_object, argumentList []Value) Value {
|
func builtinNewTypeError(obj *object, argumentList []Value) Value {
|
||||||
return toValue_object(self.runtime.newTypeError(valueOfArrayIndex(argumentList, 0)))
|
return objectValue(obj.runtime.newTypeError(valueOfArrayIndex(argumentList, 0)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (runtime *_runtime) newRangeError(message Value) *_object {
|
func (rt *runtime) newRangeError(message Value) *object {
|
||||||
self := runtime.newErrorObject("RangeError", message, 0)
|
o := rt.newErrorObject("RangeError", message, 0)
|
||||||
self.prototype = runtime.global.RangeErrorPrototype
|
o.prototype = rt.global.RangeErrorPrototype
|
||||||
return self
|
return o
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinRangeError(call FunctionCall) Value {
|
func builtinRangeError(call FunctionCall) Value {
|
||||||
return toValue_object(call.runtime.newRangeError(call.Argument(0)))
|
return objectValue(call.runtime.newRangeError(call.Argument(0)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinNewRangeError(self *_object, argumentList []Value) Value {
|
func builtinNewRangeError(obj *object, argumentList []Value) Value {
|
||||||
return toValue_object(self.runtime.newRangeError(valueOfArrayIndex(argumentList, 0)))
|
return objectValue(obj.runtime.newRangeError(valueOfArrayIndex(argumentList, 0)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (runtime *_runtime) newURIError(message Value) *_object {
|
func (rt *runtime) newURIError(message Value) *object {
|
||||||
self := runtime.newErrorObject("URIError", message, 0)
|
o := rt.newErrorObject("URIError", message, 0)
|
||||||
self.prototype = runtime.global.URIErrorPrototype
|
o.prototype = rt.global.URIErrorPrototype
|
||||||
return self
|
return o
|
||||||
}
|
}
|
||||||
|
|
||||||
func (runtime *_runtime) newReferenceError(message Value) *_object {
|
func (rt *runtime) newReferenceError(message Value) *object {
|
||||||
self := runtime.newErrorObject("ReferenceError", message, 0)
|
o := rt.newErrorObject("ReferenceError", message, 0)
|
||||||
self.prototype = runtime.global.ReferenceErrorPrototype
|
o.prototype = rt.global.ReferenceErrorPrototype
|
||||||
return self
|
return o
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinReferenceError(call FunctionCall) Value {
|
func builtinReferenceError(call FunctionCall) Value {
|
||||||
return toValue_object(call.runtime.newReferenceError(call.Argument(0)))
|
return objectValue(call.runtime.newReferenceError(call.Argument(0)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinNewReferenceError(self *_object, argumentList []Value) Value {
|
func builtinNewReferenceError(obj *object, argumentList []Value) Value {
|
||||||
return toValue_object(self.runtime.newReferenceError(valueOfArrayIndex(argumentList, 0)))
|
return objectValue(obj.runtime.newReferenceError(valueOfArrayIndex(argumentList, 0)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (runtime *_runtime) newSyntaxError(message Value) *_object {
|
func (rt *runtime) newSyntaxError(message Value) *object {
|
||||||
self := runtime.newErrorObject("SyntaxError", message, 0)
|
o := rt.newErrorObject("SyntaxError", message, 0)
|
||||||
self.prototype = runtime.global.SyntaxErrorPrototype
|
o.prototype = rt.global.SyntaxErrorPrototype
|
||||||
return self
|
return o
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinSyntaxError(call FunctionCall) Value {
|
func builtinSyntaxError(call FunctionCall) Value {
|
||||||
return toValue_object(call.runtime.newSyntaxError(call.Argument(0)))
|
return objectValue(call.runtime.newSyntaxError(call.Argument(0)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinNewSyntaxError(self *_object, argumentList []Value) Value {
|
func builtinNewSyntaxError(obj *object, argumentList []Value) Value {
|
||||||
return toValue_object(self.runtime.newSyntaxError(valueOfArrayIndex(argumentList, 0)))
|
return objectValue(obj.runtime.newSyntaxError(valueOfArrayIndex(argumentList, 0)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinURIError(call FunctionCall) Value {
|
func builtinURIError(call FunctionCall) Value {
|
||||||
return toValue_object(call.runtime.newURIError(call.Argument(0)))
|
return objectValue(call.runtime.newURIError(call.Argument(0)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinNewURIError(self *_object, argumentList []Value) Value {
|
func builtinNewURIError(obj *object, argumentList []Value) Value {
|
||||||
return toValue_object(self.runtime.newURIError(valueOfArrayIndex(argumentList, 0)))
|
return objectValue(obj.runtime.newURIError(valueOfArrayIndex(argumentList, 0)))
|
||||||
}
|
}
|
||||||
|
|
69
v1/vendor/github.com/robertkrimen/otto/builtin_function.go
generated
vendored
|
@ -11,11 +11,11 @@ import (
|
||||||
// Function
|
// Function
|
||||||
|
|
||||||
func builtinFunction(call FunctionCall) Value {
|
func builtinFunction(call FunctionCall) Value {
|
||||||
return toValue_object(builtinNewFunctionNative(call.runtime, call.ArgumentList))
|
return objectValue(builtinNewFunctionNative(call.runtime, call.ArgumentList))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinNewFunction(self *_object, argumentList []Value) Value {
|
func builtinNewFunction(obj *object, argumentList []Value) Value {
|
||||||
return toValue_object(builtinNewFunctionNative(self.runtime, argumentList))
|
return objectValue(builtinNewFunctionNative(obj.runtime, argumentList))
|
||||||
}
|
}
|
||||||
|
|
||||||
func argumentList2parameterList(argumentList []Value) []string {
|
func argumentList2parameterList(argumentList []Value) []string {
|
||||||
|
@ -29,10 +29,9 @@ func argumentList2parameterList(argumentList []Value) []string {
|
||||||
return parameterList
|
return parameterList
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinNewFunctionNative(runtime *_runtime, argumentList []Value) *_object {
|
func builtinNewFunctionNative(rt *runtime, argumentList []Value) *object {
|
||||||
var parameterList, body string
|
var parameterList, body string
|
||||||
count := len(argumentList)
|
if count := len(argumentList); count > 0 {
|
||||||
if count > 0 {
|
|
||||||
tmp := make([]string, 0, count-1)
|
tmp := make([]string, 0, count-1)
|
||||||
for _, value := range argumentList[0 : count-1] {
|
for _, value := range argumentList[0 : count-1] {
|
||||||
tmp = append(tmp, value.string())
|
tmp = append(tmp, value.string())
|
||||||
|
@ -43,35 +42,35 @@ func builtinNewFunctionNative(runtime *_runtime, argumentList []Value) *_object
|
||||||
|
|
||||||
// FIXME
|
// FIXME
|
||||||
function, err := parser.ParseFunction(parameterList, body)
|
function, err := parser.ParseFunction(parameterList, body)
|
||||||
runtime.parseThrow(err) // Will panic/throw appropriately
|
rt.parseThrow(err) // Will panic/throw appropriately
|
||||||
cmpl := _compiler{}
|
cmpl := compiler{}
|
||||||
cmpl_function := cmpl.parseExpression(function)
|
cmplFunction := cmpl.parseExpression(function)
|
||||||
|
|
||||||
return runtime.newNodeFunction(cmpl_function.(*_nodeFunctionLiteral), runtime.globalStash)
|
return rt.newNodeFunction(cmplFunction.(*nodeFunctionLiteral), rt.globalStash)
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinFunction_toString(call FunctionCall) Value {
|
func builtinFunctionToString(call FunctionCall) Value {
|
||||||
object := call.thisClassObject(classFunction) // Should throw a TypeError unless Function
|
obj := call.thisClassObject(classFunctionName) // Should throw a TypeError unless Function
|
||||||
switch fn := object.value.(type) {
|
switch fn := obj.value.(type) {
|
||||||
case _nativeFunctionObject:
|
case nativeFunctionObject:
|
||||||
return toValue_string(fmt.Sprintf("function %s() { [native code] }", fn.name))
|
return stringValue(fmt.Sprintf("function %s() { [native code] }", fn.name))
|
||||||
case _nodeFunctionObject:
|
case nodeFunctionObject:
|
||||||
return toValue_string(fn.node.source)
|
return stringValue(fn.node.source)
|
||||||
case _bindFunctionObject:
|
case bindFunctionObject:
|
||||||
return toValue_string("function () { [native code] }")
|
return stringValue("function () { [native code] }")
|
||||||
|
default:
|
||||||
|
panic(call.runtime.panicTypeError("Function.toString unknown type %T", obj.value))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
panic(call.runtime.panicTypeError("Function.toString()"))
|
func builtinFunctionApply(call FunctionCall) Value {
|
||||||
}
|
|
||||||
|
|
||||||
func builtinFunction_apply(call FunctionCall) Value {
|
|
||||||
if !call.This.isCallable() {
|
if !call.This.isCallable() {
|
||||||
panic(call.runtime.panicTypeError())
|
panic(call.runtime.panicTypeError("Function.apply %q is not callable", call.This))
|
||||||
}
|
}
|
||||||
this := call.Argument(0)
|
this := call.Argument(0)
|
||||||
if this.IsUndefined() {
|
if this.IsUndefined() {
|
||||||
// FIXME Not ECMA5
|
// FIXME Not ECMA5
|
||||||
this = toValue_object(call.runtime.globalObject)
|
this = objectValue(call.runtime.globalObject)
|
||||||
}
|
}
|
||||||
argumentList := call.Argument(1)
|
argumentList := call.Argument(1)
|
||||||
switch argumentList.kind {
|
switch argumentList.kind {
|
||||||
|
@ -79,10 +78,10 @@ func builtinFunction_apply(call FunctionCall) Value {
|
||||||
return call.thisObject().call(this, nil, false, nativeFrame)
|
return call.thisObject().call(this, nil, false, nativeFrame)
|
||||||
case valueObject:
|
case valueObject:
|
||||||
default:
|
default:
|
||||||
panic(call.runtime.panicTypeError())
|
panic(call.runtime.panicTypeError("Function.apply unknown type %T for second argument"))
|
||||||
}
|
}
|
||||||
|
|
||||||
arrayObject := argumentList._object()
|
arrayObject := argumentList.object()
|
||||||
thisObject := call.thisObject()
|
thisObject := call.thisObject()
|
||||||
length := int64(toUint32(arrayObject.get(propertyLength)))
|
length := int64(toUint32(arrayObject.get(propertyLength)))
|
||||||
valueArray := make([]Value, length)
|
valueArray := make([]Value, length)
|
||||||
|
@ -92,15 +91,15 @@ func builtinFunction_apply(call FunctionCall) Value {
|
||||||
return thisObject.call(this, valueArray, false, nativeFrame)
|
return thisObject.call(this, valueArray, false, nativeFrame)
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinFunction_call(call FunctionCall) Value {
|
func builtinFunctionCall(call FunctionCall) Value {
|
||||||
if !call.This.isCallable() {
|
if !call.This.isCallable() {
|
||||||
panic(call.runtime.panicTypeError())
|
panic(call.runtime.panicTypeError("Function.call %q is not callable", call.This))
|
||||||
}
|
}
|
||||||
thisObject := call.thisObject()
|
thisObject := call.thisObject()
|
||||||
this := call.Argument(0)
|
this := call.Argument(0)
|
||||||
if this.IsUndefined() {
|
if this.IsUndefined() {
|
||||||
// FIXME Not ECMA5
|
// FIXME Not ECMA5
|
||||||
this = toValue_object(call.runtime.globalObject)
|
this = objectValue(call.runtime.globalObject)
|
||||||
}
|
}
|
||||||
if len(call.ArgumentList) >= 1 {
|
if len(call.ArgumentList) >= 1 {
|
||||||
return thisObject.call(this, call.ArgumentList[1:], false, nativeFrame)
|
return thisObject.call(this, call.ArgumentList[1:], false, nativeFrame)
|
||||||
|
@ -108,19 +107,19 @@ func builtinFunction_call(call FunctionCall) Value {
|
||||||
return thisObject.call(this, nil, false, nativeFrame)
|
return thisObject.call(this, nil, false, nativeFrame)
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinFunction_bind(call FunctionCall) Value {
|
func builtinFunctionBind(call FunctionCall) Value {
|
||||||
target := call.This
|
target := call.This
|
||||||
if !target.isCallable() {
|
if !target.isCallable() {
|
||||||
panic(call.runtime.panicTypeError())
|
panic(call.runtime.panicTypeError("Function.bind %q is not callable", call.This))
|
||||||
}
|
}
|
||||||
targetObject := target._object()
|
targetObject := target.object()
|
||||||
|
|
||||||
this := call.Argument(0)
|
this := call.Argument(0)
|
||||||
argumentList := call.slice(1)
|
argumentList := call.slice(1)
|
||||||
if this.IsUndefined() {
|
if this.IsUndefined() {
|
||||||
// FIXME Do this elsewhere?
|
// FIXME Do this elsewhere?
|
||||||
this = toValue_object(call.runtime.globalObject)
|
this = objectValue(call.runtime.globalObject)
|
||||||
}
|
}
|
||||||
|
|
||||||
return toValue_object(call.runtime.newBoundFunction(targetObject, this, argumentList))
|
return objectValue(call.runtime.newBoundFunction(targetObject, this, argumentList))
|
||||||
}
|
}
|
||||||
|
|
154
v1/vendor/github.com/robertkrimen/otto/builtin_json.go
generated
vendored
|
@ -7,13 +7,13 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type _builtinJSON_parseContext struct {
|
type builtinJSONParseContext struct {
|
||||||
call FunctionCall
|
call FunctionCall
|
||||||
reviver Value
|
reviver Value
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinJSON_parse(call FunctionCall) Value {
|
func builtinJSONParse(call FunctionCall) Value {
|
||||||
ctx := _builtinJSON_parseContext{
|
ctx := builtinJSONParseContext{
|
||||||
call: call,
|
call: call,
|
||||||
}
|
}
|
||||||
revive := false
|
revive := false
|
||||||
|
@ -27,109 +27,107 @@ func builtinJSON_parse(call FunctionCall) Value {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(call.runtime.panicSyntaxError(err.Error()))
|
panic(call.runtime.panicSyntaxError(err.Error()))
|
||||||
}
|
}
|
||||||
value, exists := builtinJSON_parseWalk(ctx, root)
|
value, exists := builtinJSONParseWalk(ctx, root)
|
||||||
if !exists {
|
if !exists {
|
||||||
value = Value{}
|
value = Value{}
|
||||||
}
|
}
|
||||||
if revive {
|
if revive {
|
||||||
root := ctx.call.runtime.newObject()
|
root := ctx.call.runtime.newObject()
|
||||||
root.put("", value, false)
|
root.put("", value, false)
|
||||||
return builtinJSON_reviveWalk(ctx, root, "")
|
return builtinJSONReviveWalk(ctx, root, "")
|
||||||
}
|
}
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinJSON_reviveWalk(ctx _builtinJSON_parseContext, holder *_object, name string) Value {
|
func builtinJSONReviveWalk(ctx builtinJSONParseContext, holder *object, name string) Value {
|
||||||
value := holder.get(name)
|
value := holder.get(name)
|
||||||
if object := value._object(); object != nil {
|
if obj := value.object(); obj != nil {
|
||||||
if isArray(object) {
|
if isArray(obj) {
|
||||||
length := int64(objectLength(object))
|
length := int64(objectLength(obj))
|
||||||
for index := int64(0); index < length; index += 1 {
|
for index := int64(0); index < length; index++ {
|
||||||
name := arrayIndexToString(index)
|
name := arrayIndexToString(index)
|
||||||
value := builtinJSON_reviveWalk(ctx, object, name)
|
value := builtinJSONReviveWalk(ctx, obj, name)
|
||||||
if value.IsUndefined() {
|
if value.IsUndefined() {
|
||||||
object.delete(name, false)
|
obj.delete(name, false)
|
||||||
} else {
|
} else {
|
||||||
object.defineProperty(name, value, 0111, false)
|
obj.defineProperty(name, value, 0o111, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
object.enumerate(false, func(name string) bool {
|
obj.enumerate(false, func(name string) bool {
|
||||||
value := builtinJSON_reviveWalk(ctx, object, name)
|
value := builtinJSONReviveWalk(ctx, obj, name)
|
||||||
if value.IsUndefined() {
|
if value.IsUndefined() {
|
||||||
object.delete(name, false)
|
obj.delete(name, false)
|
||||||
} else {
|
} else {
|
||||||
object.defineProperty(name, value, 0111, false)
|
obj.defineProperty(name, value, 0o111, false)
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ctx.reviver.call(ctx.call.runtime, toValue_object(holder), name, value)
|
return ctx.reviver.call(ctx.call.runtime, objectValue(holder), name, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinJSON_parseWalk(ctx _builtinJSON_parseContext, rawValue interface{}) (Value, bool) {
|
func builtinJSONParseWalk(ctx builtinJSONParseContext, rawValue interface{}) (Value, bool) {
|
||||||
switch value := rawValue.(type) {
|
switch value := rawValue.(type) {
|
||||||
case nil:
|
case nil:
|
||||||
return nullValue, true
|
return nullValue, true
|
||||||
case bool:
|
case bool:
|
||||||
return toValue_bool(value), true
|
return boolValue(value), true
|
||||||
case string:
|
case string:
|
||||||
return toValue_string(value), true
|
return stringValue(value), true
|
||||||
case float64:
|
case float64:
|
||||||
return toValue_float64(value), true
|
return float64Value(value), true
|
||||||
case []interface{}:
|
case []interface{}:
|
||||||
arrayValue := make([]Value, len(value))
|
arrayValue := make([]Value, len(value))
|
||||||
for index, rawValue := range value {
|
for index, rawValue := range value {
|
||||||
if value, exists := builtinJSON_parseWalk(ctx, rawValue); exists {
|
if value, exists := builtinJSONParseWalk(ctx, rawValue); exists {
|
||||||
arrayValue[index] = value
|
arrayValue[index] = value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return toValue_object(ctx.call.runtime.newArrayOf(arrayValue)), true
|
return objectValue(ctx.call.runtime.newArrayOf(arrayValue)), true
|
||||||
case map[string]interface{}:
|
case map[string]interface{}:
|
||||||
object := ctx.call.runtime.newObject()
|
obj := ctx.call.runtime.newObject()
|
||||||
for name, rawValue := range value {
|
for name, rawValue := range value {
|
||||||
if value, exists := builtinJSON_parseWalk(ctx, rawValue); exists {
|
if value, exists := builtinJSONParseWalk(ctx, rawValue); exists {
|
||||||
object.put(name, value, false)
|
obj.put(name, value, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return toValue_object(object), true
|
return objectValue(obj), true
|
||||||
}
|
}
|
||||||
return Value{}, false
|
return Value{}, false
|
||||||
}
|
}
|
||||||
|
|
||||||
type _builtinJSON_stringifyContext struct {
|
type builtinJSONStringifyContext struct {
|
||||||
call FunctionCall
|
call FunctionCall
|
||||||
stack []*_object
|
stack []*object
|
||||||
propertyList []string
|
propertyList []string
|
||||||
replacerFunction *Value
|
replacerFunction *Value
|
||||||
gap string
|
gap string
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinJSON_stringify(call FunctionCall) Value {
|
func builtinJSONStringify(call FunctionCall) Value {
|
||||||
ctx := _builtinJSON_stringifyContext{
|
ctx := builtinJSONStringifyContext{
|
||||||
call: call,
|
call: call,
|
||||||
stack: []*_object{nil},
|
stack: []*object{nil},
|
||||||
}
|
}
|
||||||
replacer := call.Argument(1)._object()
|
replacer := call.Argument(1).object()
|
||||||
if replacer != nil {
|
if replacer != nil {
|
||||||
if isArray(replacer) {
|
if isArray(replacer) {
|
||||||
length := objectLength(replacer)
|
length := objectLength(replacer)
|
||||||
seen := map[string]bool{}
|
seen := map[string]bool{}
|
||||||
propertyList := make([]string, length)
|
propertyList := make([]string, length)
|
||||||
length = 0
|
length = 0
|
||||||
for index, _ := range propertyList {
|
for index := range propertyList {
|
||||||
value := replacer.get(arrayIndexToString(int64(index)))
|
value := replacer.get(arrayIndexToString(int64(index)))
|
||||||
switch value.kind {
|
switch value.kind {
|
||||||
case valueObject:
|
case valueObject:
|
||||||
switch value.value.(*_object).class {
|
switch value.value.(*object).class {
|
||||||
case classString:
|
case classStringName, classNumberName:
|
||||||
case classNumber:
|
|
||||||
default:
|
default:
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
case valueString:
|
case valueString, valueNumber:
|
||||||
case valueNumber:
|
|
||||||
default:
|
default:
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -138,21 +136,21 @@ func builtinJSON_stringify(call FunctionCall) Value {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
seen[name] = true
|
seen[name] = true
|
||||||
length += 1
|
length++
|
||||||
propertyList[index] = name
|
propertyList[index] = name
|
||||||
}
|
}
|
||||||
ctx.propertyList = propertyList[0:length]
|
ctx.propertyList = propertyList[0:length]
|
||||||
} else if replacer.class == classFunction {
|
} else if replacer.class == classFunctionName {
|
||||||
value := toValue_object(replacer)
|
value := objectValue(replacer)
|
||||||
ctx.replacerFunction = &value
|
ctx.replacerFunction = &value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if spaceValue, exists := call.getArgument(2); exists {
|
if spaceValue, exists := call.getArgument(2); exists {
|
||||||
if spaceValue.kind == valueObject {
|
if spaceValue.kind == valueObject {
|
||||||
switch spaceValue.value.(*_object).class {
|
switch spaceValue.value.(*object).class {
|
||||||
case classString:
|
case classStringName:
|
||||||
spaceValue = toValue_string(spaceValue.string())
|
spaceValue = stringValue(spaceValue.string())
|
||||||
case classNumber:
|
case classNumberName:
|
||||||
spaceValue = spaceValue.numberValue()
|
spaceValue = spaceValue.numberValue()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -176,51 +174,51 @@ func builtinJSON_stringify(call FunctionCall) Value {
|
||||||
}
|
}
|
||||||
holder := call.runtime.newObject()
|
holder := call.runtime.newObject()
|
||||||
holder.put("", call.Argument(0), false)
|
holder.put("", call.Argument(0), false)
|
||||||
value, exists := builtinJSON_stringifyWalk(ctx, "", holder)
|
value, exists := builtinJSONStringifyWalk(ctx, "", holder)
|
||||||
if !exists {
|
if !exists {
|
||||||
return Value{}
|
return Value{}
|
||||||
}
|
}
|
||||||
valueJSON, err := json.Marshal(value)
|
valueJSON, err := json.Marshal(value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(call.runtime.panicTypeError(err.Error()))
|
panic(call.runtime.panicTypeError("JSON.stringify marshal: %s", err))
|
||||||
}
|
}
|
||||||
if ctx.gap != "" {
|
if ctx.gap != "" {
|
||||||
valueJSON1 := bytes.Buffer{}
|
valueJSON1 := bytes.Buffer{}
|
||||||
json.Indent(&valueJSON1, valueJSON, "", ctx.gap)
|
if err = json.Indent(&valueJSON1, valueJSON, "", ctx.gap); err != nil {
|
||||||
|
panic(call.runtime.panicTypeError("JSON.stringify indent: %s", err))
|
||||||
|
}
|
||||||
valueJSON = valueJSON1.Bytes()
|
valueJSON = valueJSON1.Bytes()
|
||||||
}
|
}
|
||||||
return toValue_string(string(valueJSON))
|
return stringValue(string(valueJSON))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinJSON_stringifyWalk(ctx _builtinJSON_stringifyContext, key string, holder *_object) (interface{}, bool) {
|
func builtinJSONStringifyWalk(ctx builtinJSONStringifyContext, key string, holder *object) (interface{}, bool) {
|
||||||
value := holder.get(key)
|
value := holder.get(key)
|
||||||
|
|
||||||
if value.IsObject() {
|
if value.IsObject() {
|
||||||
object := value._object()
|
obj := value.object()
|
||||||
if toJSON := object.get("toJSON"); toJSON.IsFunction() {
|
if toJSON := obj.get("toJSON"); toJSON.IsFunction() {
|
||||||
value = toJSON.call(ctx.call.runtime, value, key)
|
value = toJSON.call(ctx.call.runtime, value, key)
|
||||||
} else {
|
} else if obj.objectClass.marshalJSON != nil {
|
||||||
// If the object is a GoStruct or something that implements json.Marshaler
|
// If the object is a GoStruct or something that implements json.Marshaler
|
||||||
if object.objectClass.marshalJSON != nil {
|
marshaler := obj.objectClass.marshalJSON(obj)
|
||||||
marshaler := object.objectClass.marshalJSON(object)
|
|
||||||
if marshaler != nil {
|
if marshaler != nil {
|
||||||
return marshaler, true
|
return marshaler, true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if ctx.replacerFunction != nil {
|
if ctx.replacerFunction != nil {
|
||||||
value = ctx.replacerFunction.call(ctx.call.runtime, toValue_object(holder), key, value)
|
value = ctx.replacerFunction.call(ctx.call.runtime, objectValue(holder), key, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
if value.kind == valueObject {
|
if value.kind == valueObject {
|
||||||
switch value.value.(*_object).class {
|
switch value.value.(*object).class {
|
||||||
case classBoolean:
|
case classBooleanName:
|
||||||
value = value._object().value.(Value)
|
value = value.object().value.(Value)
|
||||||
case classString:
|
case classStringName:
|
||||||
value = toValue_string(value.string())
|
value = stringValue(value.string())
|
||||||
case classNumber:
|
case classNumberName:
|
||||||
value = value.numberValue()
|
value = value.numberValue()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -243,10 +241,10 @@ func builtinJSON_stringifyWalk(ctx _builtinJSON_stringifyContext, key string, ho
|
||||||
case valueNull:
|
case valueNull:
|
||||||
return nil, true
|
return nil, true
|
||||||
case valueObject:
|
case valueObject:
|
||||||
holder := value._object()
|
holder := value.object()
|
||||||
if value := value._object(); nil != value {
|
if value := value.object(); nil != value {
|
||||||
for _, object := range ctx.stack {
|
for _, obj := range ctx.stack {
|
||||||
if holder == object {
|
if holder == obj {
|
||||||
panic(ctx.call.runtime.panicTypeError("Converting circular structure to JSON"))
|
panic(ctx.call.runtime.panicTypeError("Converting circular structure to JSON"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -266,33 +264,33 @@ func builtinJSON_stringifyWalk(ctx _builtinJSON_stringifyContext, key string, ho
|
||||||
panic(ctx.call.runtime.panicTypeError(fmt.Sprintf("JSON.stringify: invalid length: %v (%[1]T)", value)))
|
panic(ctx.call.runtime.panicTypeError(fmt.Sprintf("JSON.stringify: invalid length: %v (%[1]T)", value)))
|
||||||
}
|
}
|
||||||
array := make([]interface{}, length)
|
array := make([]interface{}, length)
|
||||||
for index, _ := range array {
|
for index := range array {
|
||||||
name := arrayIndexToString(int64(index))
|
name := arrayIndexToString(int64(index))
|
||||||
value, _ := builtinJSON_stringifyWalk(ctx, name, holder)
|
value, _ := builtinJSONStringifyWalk(ctx, name, holder)
|
||||||
array[index] = value
|
array[index] = value
|
||||||
}
|
}
|
||||||
return array, true
|
return array, true
|
||||||
} else if holder.class != classFunction {
|
} else if holder.class != classFunctionName {
|
||||||
object := map[string]interface{}{}
|
obj := map[string]interface{}{}
|
||||||
if ctx.propertyList != nil {
|
if ctx.propertyList != nil {
|
||||||
for _, name := range ctx.propertyList {
|
for _, name := range ctx.propertyList {
|
||||||
value, exists := builtinJSON_stringifyWalk(ctx, name, holder)
|
value, exists := builtinJSONStringifyWalk(ctx, name, holder)
|
||||||
if exists {
|
if exists {
|
||||||
object[name] = value
|
obj[name] = value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Go maps are without order, so this doesn't conform to the ECMA ordering
|
// Go maps are without order, so this doesn't conform to the ECMA ordering
|
||||||
// standard, but oh well...
|
// standard, but oh well...
|
||||||
holder.enumerate(false, func(name string) bool {
|
holder.enumerate(false, func(name string) bool {
|
||||||
value, exists := builtinJSON_stringifyWalk(ctx, name, holder)
|
value, exists := builtinJSONStringifyWalk(ctx, name, holder)
|
||||||
if exists {
|
if exists {
|
||||||
object[name] = value
|
obj[name] = value
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return object, true
|
return obj, true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil, false
|
return nil, false
|
||||||
|
|
138
v1/vendor/github.com/robertkrimen/otto/builtin_math.go
generated
vendored
|
@ -7,27 +7,37 @@ import (
|
||||||
|
|
||||||
// Math
|
// Math
|
||||||
|
|
||||||
func builtinMath_abs(call FunctionCall) Value {
|
func builtinMathAbs(call FunctionCall) Value {
|
||||||
number := call.Argument(0).float64()
|
number := call.Argument(0).float64()
|
||||||
return toValue_float64(math.Abs(number))
|
return float64Value(math.Abs(number))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinMath_acos(call FunctionCall) Value {
|
func builtinMathAcos(call FunctionCall) Value {
|
||||||
number := call.Argument(0).float64()
|
number := call.Argument(0).float64()
|
||||||
return toValue_float64(math.Acos(number))
|
return float64Value(math.Acos(number))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinMath_asin(call FunctionCall) Value {
|
func builtinMathAcosh(call FunctionCall) Value {
|
||||||
number := call.Argument(0).float64()
|
number := call.Argument(0).float64()
|
||||||
return toValue_float64(math.Asin(number))
|
return float64Value(math.Acosh(number))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinMath_atan(call FunctionCall) Value {
|
func builtinMathAsin(call FunctionCall) Value {
|
||||||
number := call.Argument(0).float64()
|
number := call.Argument(0).float64()
|
||||||
return toValue_float64(math.Atan(number))
|
return float64Value(math.Asin(number))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinMath_atan2(call FunctionCall) Value {
|
func builtinMathAsinh(call FunctionCall) Value {
|
||||||
|
number := call.Argument(0).float64()
|
||||||
|
return float64Value(math.Asinh(number))
|
||||||
|
}
|
||||||
|
|
||||||
|
func builtinMathAtan(call FunctionCall) Value {
|
||||||
|
number := call.Argument(0).float64()
|
||||||
|
return float64Value(math.Atan(number))
|
||||||
|
}
|
||||||
|
|
||||||
|
func builtinMathAtan2(call FunctionCall) Value {
|
||||||
y := call.Argument(0).float64()
|
y := call.Argument(0).float64()
|
||||||
if math.IsNaN(y) {
|
if math.IsNaN(y) {
|
||||||
return NaNValue()
|
return NaNValue()
|
||||||
|
@ -36,40 +46,75 @@ func builtinMath_atan2(call FunctionCall) Value {
|
||||||
if math.IsNaN(x) {
|
if math.IsNaN(x) {
|
||||||
return NaNValue()
|
return NaNValue()
|
||||||
}
|
}
|
||||||
return toValue_float64(math.Atan2(y, x))
|
return float64Value(math.Atan2(y, x))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinMath_cos(call FunctionCall) Value {
|
func builtinMathAtanh(call FunctionCall) Value {
|
||||||
number := call.Argument(0).float64()
|
number := call.Argument(0).float64()
|
||||||
return toValue_float64(math.Cos(number))
|
return float64Value(math.Atanh(number))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinMath_ceil(call FunctionCall) Value {
|
func builtinMathCbrt(call FunctionCall) Value {
|
||||||
number := call.Argument(0).float64()
|
number := call.Argument(0).float64()
|
||||||
return toValue_float64(math.Ceil(number))
|
return float64Value(math.Cbrt(number))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinMath_exp(call FunctionCall) Value {
|
func builtinMathCos(call FunctionCall) Value {
|
||||||
number := call.Argument(0).float64()
|
number := call.Argument(0).float64()
|
||||||
return toValue_float64(math.Exp(number))
|
return float64Value(math.Cos(number))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinMath_floor(call FunctionCall) Value {
|
func builtinMathCeil(call FunctionCall) Value {
|
||||||
number := call.Argument(0).float64()
|
number := call.Argument(0).float64()
|
||||||
return toValue_float64(math.Floor(number))
|
return float64Value(math.Ceil(number))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinMath_log(call FunctionCall) Value {
|
func builtinMathCosh(call FunctionCall) Value {
|
||||||
number := call.Argument(0).float64()
|
number := call.Argument(0).float64()
|
||||||
return toValue_float64(math.Log(number))
|
return float64Value(math.Cosh(number))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinMath_max(call FunctionCall) Value {
|
func builtinMathExp(call FunctionCall) Value {
|
||||||
|
number := call.Argument(0).float64()
|
||||||
|
return float64Value(math.Exp(number))
|
||||||
|
}
|
||||||
|
|
||||||
|
func builtinMathExpm1(call FunctionCall) Value {
|
||||||
|
number := call.Argument(0).float64()
|
||||||
|
return float64Value(math.Expm1(number))
|
||||||
|
}
|
||||||
|
|
||||||
|
func builtinMathFloor(call FunctionCall) Value {
|
||||||
|
number := call.Argument(0).float64()
|
||||||
|
return float64Value(math.Floor(number))
|
||||||
|
}
|
||||||
|
|
||||||
|
func builtinMathLog(call FunctionCall) Value {
|
||||||
|
number := call.Argument(0).float64()
|
||||||
|
return float64Value(math.Log(number))
|
||||||
|
}
|
||||||
|
|
||||||
|
func builtinMathLog10(call FunctionCall) Value {
|
||||||
|
number := call.Argument(0).float64()
|
||||||
|
return float64Value(math.Log10(number))
|
||||||
|
}
|
||||||
|
|
||||||
|
func builtinMathLog1p(call FunctionCall) Value {
|
||||||
|
number := call.Argument(0).float64()
|
||||||
|
return float64Value(math.Log1p(number))
|
||||||
|
}
|
||||||
|
|
||||||
|
func builtinMathLog2(call FunctionCall) Value {
|
||||||
|
number := call.Argument(0).float64()
|
||||||
|
return float64Value(math.Log2(number))
|
||||||
|
}
|
||||||
|
|
||||||
|
func builtinMathMax(call FunctionCall) Value {
|
||||||
switch len(call.ArgumentList) {
|
switch len(call.ArgumentList) {
|
||||||
case 0:
|
case 0:
|
||||||
return negativeInfinityValue()
|
return negativeInfinityValue()
|
||||||
case 1:
|
case 1:
|
||||||
return toValue_float64(call.ArgumentList[0].float64())
|
return float64Value(call.ArgumentList[0].float64())
|
||||||
}
|
}
|
||||||
result := call.ArgumentList[0].float64()
|
result := call.ArgumentList[0].float64()
|
||||||
if math.IsNaN(result) {
|
if math.IsNaN(result) {
|
||||||
|
@ -82,15 +127,15 @@ func builtinMath_max(call FunctionCall) Value {
|
||||||
}
|
}
|
||||||
result = math.Max(result, value)
|
result = math.Max(result, value)
|
||||||
}
|
}
|
||||||
return toValue_float64(result)
|
return float64Value(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinMath_min(call FunctionCall) Value {
|
func builtinMathMin(call FunctionCall) Value {
|
||||||
switch len(call.ArgumentList) {
|
switch len(call.ArgumentList) {
|
||||||
case 0:
|
case 0:
|
||||||
return positiveInfinityValue()
|
return positiveInfinityValue()
|
||||||
case 1:
|
case 1:
|
||||||
return toValue_float64(call.ArgumentList[0].float64())
|
return float64Value(call.ArgumentList[0].float64())
|
||||||
}
|
}
|
||||||
result := call.ArgumentList[0].float64()
|
result := call.ArgumentList[0].float64()
|
||||||
if math.IsNaN(result) {
|
if math.IsNaN(result) {
|
||||||
|
@ -103,49 +148,64 @@ func builtinMath_min(call FunctionCall) Value {
|
||||||
}
|
}
|
||||||
result = math.Min(result, value)
|
result = math.Min(result, value)
|
||||||
}
|
}
|
||||||
return toValue_float64(result)
|
return float64Value(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinMath_pow(call FunctionCall) Value {
|
func builtinMathPow(call FunctionCall) Value {
|
||||||
// TODO Make sure this works according to the specification (15.8.2.13)
|
// TODO Make sure this works according to the specification (15.8.2.13)
|
||||||
x := call.Argument(0).float64()
|
x := call.Argument(0).float64()
|
||||||
y := call.Argument(1).float64()
|
y := call.Argument(1).float64()
|
||||||
if math.Abs(x) == 1 && math.IsInf(y, 0) {
|
if math.Abs(x) == 1 && math.IsInf(y, 0) {
|
||||||
return NaNValue()
|
return NaNValue()
|
||||||
}
|
}
|
||||||
return toValue_float64(math.Pow(x, y))
|
return float64Value(math.Pow(x, y))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinMath_random(call FunctionCall) Value {
|
func builtinMathRandom(call FunctionCall) Value {
|
||||||
var v float64
|
var v float64
|
||||||
if call.runtime.random != nil {
|
if call.runtime.random != nil {
|
||||||
v = call.runtime.random()
|
v = call.runtime.random()
|
||||||
} else {
|
} else {
|
||||||
v = rand.Float64()
|
v = rand.Float64() //nolint: gosec
|
||||||
}
|
}
|
||||||
return toValue_float64(v)
|
return float64Value(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinMath_round(call FunctionCall) Value {
|
func builtinMathRound(call FunctionCall) Value {
|
||||||
number := call.Argument(0).float64()
|
number := call.Argument(0).float64()
|
||||||
value := math.Floor(number + 0.5)
|
value := math.Floor(number + 0.5)
|
||||||
if value == 0 {
|
if value == 0 {
|
||||||
value = math.Copysign(0, number)
|
value = math.Copysign(0, number)
|
||||||
}
|
}
|
||||||
return toValue_float64(value)
|
return float64Value(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinMath_sin(call FunctionCall) Value {
|
func builtinMathSin(call FunctionCall) Value {
|
||||||
number := call.Argument(0).float64()
|
number := call.Argument(0).float64()
|
||||||
return toValue_float64(math.Sin(number))
|
return float64Value(math.Sin(number))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinMath_sqrt(call FunctionCall) Value {
|
func builtinMathSinh(call FunctionCall) Value {
|
||||||
number := call.Argument(0).float64()
|
number := call.Argument(0).float64()
|
||||||
return toValue_float64(math.Sqrt(number))
|
return float64Value(math.Sinh(number))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinMath_tan(call FunctionCall) Value {
|
func builtinMathSqrt(call FunctionCall) Value {
|
||||||
number := call.Argument(0).float64()
|
number := call.Argument(0).float64()
|
||||||
return toValue_float64(math.Tan(number))
|
return float64Value(math.Sqrt(number))
|
||||||
|
}
|
||||||
|
|
||||||
|
func builtinMathTan(call FunctionCall) Value {
|
||||||
|
number := call.Argument(0).float64()
|
||||||
|
return float64Value(math.Tan(number))
|
||||||
|
}
|
||||||
|
|
||||||
|
func builtinMathTanh(call FunctionCall) Value {
|
||||||
|
number := call.Argument(0).float64()
|
||||||
|
return float64Value(math.Tanh(number))
|
||||||
|
}
|
||||||
|
|
||||||
|
func builtinMathTrunc(call FunctionCall) Value {
|
||||||
|
number := call.Argument(0).float64()
|
||||||
|
return float64Value(math.Trunc(number))
|
||||||
}
|
}
|
||||||
|
|
55
v1/vendor/github.com/robertkrimen/otto/builtin_number.go
generated
vendored
|
@ -15,20 +15,20 @@ func numberValueFromNumberArgumentList(argumentList []Value) Value {
|
||||||
if len(argumentList) > 0 {
|
if len(argumentList) > 0 {
|
||||||
return argumentList[0].numberValue()
|
return argumentList[0].numberValue()
|
||||||
}
|
}
|
||||||
return toValue_int(0)
|
return intValue(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinNumber(call FunctionCall) Value {
|
func builtinNumber(call FunctionCall) Value {
|
||||||
return numberValueFromNumberArgumentList(call.ArgumentList)
|
return numberValueFromNumberArgumentList(call.ArgumentList)
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinNewNumber(self *_object, argumentList []Value) Value {
|
func builtinNewNumber(obj *object, argumentList []Value) Value {
|
||||||
return toValue_object(self.runtime.newNumber(numberValueFromNumberArgumentList(argumentList)))
|
return objectValue(obj.runtime.newNumber(numberValueFromNumberArgumentList(argumentList)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinNumber_toString(call FunctionCall) Value {
|
func builtinNumberToString(call FunctionCall) Value {
|
||||||
// Will throw a TypeError if ThisObject is not a Number
|
// Will throw a TypeError if ThisObject is not a Number
|
||||||
value := call.thisClassObject(classNumber).primitiveValue()
|
value := call.thisClassObject(classNumberName).primitiveValue()
|
||||||
radix := 10
|
radix := 10
|
||||||
radixArgument := call.Argument(0)
|
radixArgument := call.Argument(0)
|
||||||
if radixArgument.IsDefined() {
|
if radixArgument.IsDefined() {
|
||||||
|
@ -39,33 +39,32 @@ func builtinNumber_toString(call FunctionCall) Value {
|
||||||
radix = int(integer)
|
radix = int(integer)
|
||||||
}
|
}
|
||||||
if radix == 10 {
|
if radix == 10 {
|
||||||
return toValue_string(value.string())
|
return stringValue(value.string())
|
||||||
}
|
}
|
||||||
return toValue_string(numberToStringRadix(value, radix))
|
return stringValue(numberToStringRadix(value, radix))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinNumber_valueOf(call FunctionCall) Value {
|
func builtinNumberValueOf(call FunctionCall) Value {
|
||||||
return call.thisClassObject(classNumber).primitiveValue()
|
return call.thisClassObject(classNumberName).primitiveValue()
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinNumber_toFixed(call FunctionCall) Value {
|
func builtinNumberToFixed(call FunctionCall) Value {
|
||||||
precision := toIntegerFloat(call.Argument(0))
|
precision := toIntegerFloat(call.Argument(0))
|
||||||
if 20 < precision || 0 > precision {
|
if 20 < precision || 0 > precision {
|
||||||
panic(call.runtime.panicRangeError("toFixed() precision must be between 0 and 20"))
|
panic(call.runtime.panicRangeError("toFixed() precision must be between 0 and 20"))
|
||||||
}
|
}
|
||||||
if call.This.IsNaN() {
|
if call.This.IsNaN() {
|
||||||
return toValue_string("NaN")
|
return stringValue("NaN")
|
||||||
}
|
}
|
||||||
value := call.This.float64()
|
if value := call.This.float64(); math.Abs(value) >= 1e21 {
|
||||||
if math.Abs(value) >= 1e21 {
|
return stringValue(floatToString(value, 64))
|
||||||
return toValue_string(floatToString(value, 64))
|
|
||||||
}
|
}
|
||||||
return toValue_string(strconv.FormatFloat(call.This.float64(), 'f', int(precision), 64))
|
return stringValue(strconv.FormatFloat(call.This.float64(), 'f', int(precision), 64))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinNumber_toExponential(call FunctionCall) Value {
|
func builtinNumberToExponential(call FunctionCall) Value {
|
||||||
if call.This.IsNaN() {
|
if call.This.IsNaN() {
|
||||||
return toValue_string("NaN")
|
return stringValue("NaN")
|
||||||
}
|
}
|
||||||
precision := float64(-1)
|
precision := float64(-1)
|
||||||
if value := call.Argument(0); value.IsDefined() {
|
if value := call.Argument(0); value.IsDefined() {
|
||||||
|
@ -74,33 +73,33 @@ func builtinNumber_toExponential(call FunctionCall) Value {
|
||||||
panic(call.runtime.panicRangeError("toString() radix must be between 2 and 36"))
|
panic(call.runtime.panicRangeError("toString() radix must be between 2 and 36"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return toValue_string(strconv.FormatFloat(call.This.float64(), 'e', int(precision), 64))
|
return stringValue(strconv.FormatFloat(call.This.float64(), 'e', int(precision), 64))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinNumber_toPrecision(call FunctionCall) Value {
|
func builtinNumberToPrecision(call FunctionCall) Value {
|
||||||
if call.This.IsNaN() {
|
if call.This.IsNaN() {
|
||||||
return toValue_string("NaN")
|
return stringValue("NaN")
|
||||||
}
|
}
|
||||||
value := call.Argument(0)
|
value := call.Argument(0)
|
||||||
if value.IsUndefined() {
|
if value.IsUndefined() {
|
||||||
return toValue_string(call.This.string())
|
return stringValue(call.This.string())
|
||||||
}
|
}
|
||||||
precision := toIntegerFloat(value)
|
precision := toIntegerFloat(value)
|
||||||
if 1 > precision {
|
if 1 > precision {
|
||||||
panic(call.runtime.panicRangeError("toPrecision() precision must be greater than 1"))
|
panic(call.runtime.panicRangeError("toPrecision() precision must be greater than 1"))
|
||||||
}
|
}
|
||||||
return toValue_string(strconv.FormatFloat(call.This.float64(), 'g', int(precision), 64))
|
return stringValue(strconv.FormatFloat(call.This.float64(), 'g', int(precision), 64))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinNumber_isNaN(call FunctionCall) Value {
|
func builtinNumberIsNaN(call FunctionCall) Value {
|
||||||
if len(call.ArgumentList) < 1 {
|
if len(call.ArgumentList) < 1 {
|
||||||
return toValue_bool(false)
|
return boolValue(false)
|
||||||
}
|
}
|
||||||
return toValue_bool(call.Argument(0).IsNaN())
|
return boolValue(call.Argument(0).IsNaN())
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinNumber_toLocaleString(call FunctionCall) Value {
|
func builtinNumberToLocaleString(call FunctionCall) Value {
|
||||||
value := call.thisClassObject(classNumber).primitiveValue()
|
value := call.thisClassObject(classNumberName).primitiveValue()
|
||||||
locale := call.Argument(0)
|
locale := call.Argument(0)
|
||||||
lang := defaultLanguage
|
lang := defaultLanguage
|
||||||
if locale.IsDefined() {
|
if locale.IsDefined() {
|
||||||
|
@ -108,5 +107,5 @@ func builtinNumber_toLocaleString(call FunctionCall) Value {
|
||||||
}
|
}
|
||||||
|
|
||||||
p := message.NewPrinter(lang)
|
p := message.NewPrinter(lang)
|
||||||
return toValue_string(p.Sprintf("%v", number.Decimal(value.value)))
|
return stringValue(p.Sprintf("%v", number.Decimal(value.value)))
|
||||||
}
|
}
|
||||||
|
|
248
v1/vendor/github.com/robertkrimen/otto/builtin_object.go
generated
vendored
|
@ -10,36 +10,36 @@ func builtinObject(call FunctionCall) Value {
|
||||||
value := call.Argument(0)
|
value := call.Argument(0)
|
||||||
switch value.kind {
|
switch value.kind {
|
||||||
case valueUndefined, valueNull:
|
case valueUndefined, valueNull:
|
||||||
return toValue_object(call.runtime.newObject())
|
return objectValue(call.runtime.newObject())
|
||||||
}
|
}
|
||||||
|
|
||||||
return toValue_object(call.runtime.toObject(value))
|
return objectValue(call.runtime.toObject(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinNewObject(self *_object, argumentList []Value) Value {
|
func builtinNewObject(obj *object, argumentList []Value) Value {
|
||||||
value := valueOfArrayIndex(argumentList, 0)
|
value := valueOfArrayIndex(argumentList, 0)
|
||||||
switch value.kind {
|
switch value.kind {
|
||||||
case valueNull, valueUndefined:
|
case valueNull, valueUndefined:
|
||||||
case valueNumber, valueString, valueBoolean:
|
case valueNumber, valueString, valueBoolean:
|
||||||
return toValue_object(self.runtime.toObject(value))
|
return objectValue(obj.runtime.toObject(value))
|
||||||
case valueObject:
|
case valueObject:
|
||||||
return value
|
return value
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
return toValue_object(self.runtime.newObject())
|
return objectValue(obj.runtime.newObject())
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinObject_valueOf(call FunctionCall) Value {
|
func builtinObjectValueOf(call FunctionCall) Value {
|
||||||
return toValue_object(call.thisObject())
|
return objectValue(call.thisObject())
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinObject_hasOwnProperty(call FunctionCall) Value {
|
func builtinObjectHasOwnProperty(call FunctionCall) Value {
|
||||||
propertyName := call.Argument(0).string()
|
propertyName := call.Argument(0).string()
|
||||||
thisObject := call.thisObject()
|
thisObject := call.thisObject()
|
||||||
return toValue_bool(thisObject.hasOwnProperty(propertyName))
|
return boolValue(thisObject.hasOwnProperty(propertyName))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinObject_isPrototypeOf(call FunctionCall) Value {
|
func builtinObjectIsPrototypeOf(call FunctionCall) Value {
|
||||||
value := call.Argument(0)
|
value := call.Argument(0)
|
||||||
if !value.IsObject() {
|
if !value.IsObject() {
|
||||||
return falseValue
|
return falseValue
|
||||||
|
@ -55,235 +55,235 @@ func builtinObject_isPrototypeOf(call FunctionCall) Value {
|
||||||
return falseValue
|
return falseValue
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinObject_propertyIsEnumerable(call FunctionCall) Value {
|
func builtinObjectPropertyIsEnumerable(call FunctionCall) Value {
|
||||||
propertyName := call.Argument(0).string()
|
propertyName := call.Argument(0).string()
|
||||||
thisObject := call.thisObject()
|
thisObject := call.thisObject()
|
||||||
property := thisObject.getOwnProperty(propertyName)
|
prop := thisObject.getOwnProperty(propertyName)
|
||||||
if property != nil && property.enumerable() {
|
if prop != nil && prop.enumerable() {
|
||||||
return trueValue
|
return trueValue
|
||||||
}
|
}
|
||||||
return falseValue
|
return falseValue
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinObject_toString(call FunctionCall) Value {
|
func builtinObjectToString(call FunctionCall) Value {
|
||||||
var result string
|
var result string
|
||||||
if call.This.IsUndefined() {
|
switch {
|
||||||
|
case call.This.IsUndefined():
|
||||||
result = "[object Undefined]"
|
result = "[object Undefined]"
|
||||||
} else if call.This.IsNull() {
|
case call.This.IsNull():
|
||||||
result = "[object Null]"
|
result = "[object Null]"
|
||||||
} else {
|
default:
|
||||||
result = fmt.Sprintf("[object %s]", call.thisObject().class)
|
result = fmt.Sprintf("[object %s]", call.thisObject().class)
|
||||||
}
|
}
|
||||||
return toValue_string(result)
|
return stringValue(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinObject_toLocaleString(call FunctionCall) Value {
|
func builtinObjectToLocaleString(call FunctionCall) Value {
|
||||||
toString := call.thisObject().get("toString")
|
toString := call.thisObject().get("toString")
|
||||||
if !toString.isCallable() {
|
if !toString.isCallable() {
|
||||||
panic(call.runtime.panicTypeError())
|
panic(call.runtime.panicTypeError("Object.toLocaleString %q is not callable", toString))
|
||||||
}
|
}
|
||||||
return toString.call(call.runtime, call.This)
|
return toString.call(call.runtime, call.This)
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinObject_getPrototypeOf(call FunctionCall) Value {
|
func builtinObjectGetPrototypeOf(call FunctionCall) Value {
|
||||||
objectValue := call.Argument(0)
|
val := call.Argument(0)
|
||||||
object := objectValue._object()
|
obj := val.object()
|
||||||
if object == nil {
|
if obj == nil {
|
||||||
panic(call.runtime.panicTypeError())
|
panic(call.runtime.panicTypeError("Object.GetPrototypeOf is nil"))
|
||||||
}
|
}
|
||||||
|
|
||||||
if object.prototype == nil {
|
if obj.prototype == nil {
|
||||||
return nullValue
|
return nullValue
|
||||||
}
|
}
|
||||||
|
|
||||||
return toValue_object(object.prototype)
|
return objectValue(obj.prototype)
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinObject_getOwnPropertyDescriptor(call FunctionCall) Value {
|
func builtinObjectGetOwnPropertyDescriptor(call FunctionCall) Value {
|
||||||
objectValue := call.Argument(0)
|
val := call.Argument(0)
|
||||||
object := objectValue._object()
|
obj := val.object()
|
||||||
if object == nil {
|
if obj == nil {
|
||||||
panic(call.runtime.panicTypeError())
|
panic(call.runtime.panicTypeError("Object.GetOwnPropertyDescriptor is nil"))
|
||||||
}
|
}
|
||||||
|
|
||||||
name := call.Argument(1).string()
|
name := call.Argument(1).string()
|
||||||
descriptor := object.getOwnProperty(name)
|
descriptor := obj.getOwnProperty(name)
|
||||||
if descriptor == nil {
|
if descriptor == nil {
|
||||||
return Value{}
|
return Value{}
|
||||||
}
|
}
|
||||||
return toValue_object(call.runtime.fromPropertyDescriptor(*descriptor))
|
return objectValue(call.runtime.fromPropertyDescriptor(*descriptor))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinObject_defineProperty(call FunctionCall) Value {
|
func builtinObjectDefineProperty(call FunctionCall) Value {
|
||||||
objectValue := call.Argument(0)
|
val := call.Argument(0)
|
||||||
object := objectValue._object()
|
obj := val.object()
|
||||||
if object == nil {
|
if obj == nil {
|
||||||
panic(call.runtime.panicTypeError())
|
panic(call.runtime.panicTypeError("Object.DefineProperty is nil"))
|
||||||
}
|
}
|
||||||
name := call.Argument(1).string()
|
name := call.Argument(1).string()
|
||||||
descriptor := toPropertyDescriptor(call.runtime, call.Argument(2))
|
descriptor := toPropertyDescriptor(call.runtime, call.Argument(2))
|
||||||
object.defineOwnProperty(name, descriptor, true)
|
obj.defineOwnProperty(name, descriptor, true)
|
||||||
return objectValue
|
return val
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinObject_defineProperties(call FunctionCall) Value {
|
func builtinObjectDefineProperties(call FunctionCall) Value {
|
||||||
objectValue := call.Argument(0)
|
val := call.Argument(0)
|
||||||
object := objectValue._object()
|
obj := val.object()
|
||||||
if object == nil {
|
if obj == nil {
|
||||||
panic(call.runtime.panicTypeError())
|
panic(call.runtime.panicTypeError("Object.DefineProperties is nil"))
|
||||||
}
|
}
|
||||||
|
|
||||||
properties := call.runtime.toObject(call.Argument(1))
|
properties := call.runtime.toObject(call.Argument(1))
|
||||||
properties.enumerate(false, func(name string) bool {
|
properties.enumerate(false, func(name string) bool {
|
||||||
descriptor := toPropertyDescriptor(call.runtime, properties.get(name))
|
descriptor := toPropertyDescriptor(call.runtime, properties.get(name))
|
||||||
object.defineOwnProperty(name, descriptor, true)
|
obj.defineOwnProperty(name, descriptor, true)
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
|
|
||||||
return objectValue
|
return val
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinObject_create(call FunctionCall) Value {
|
func builtinObjectCreate(call FunctionCall) Value {
|
||||||
prototypeValue := call.Argument(0)
|
prototypeValue := call.Argument(0)
|
||||||
if !prototypeValue.IsNull() && !prototypeValue.IsObject() {
|
if !prototypeValue.IsNull() && !prototypeValue.IsObject() {
|
||||||
panic(call.runtime.panicTypeError())
|
panic(call.runtime.panicTypeError("Object.Create is nil"))
|
||||||
}
|
}
|
||||||
|
|
||||||
object := call.runtime.newObject()
|
obj := call.runtime.newObject()
|
||||||
object.prototype = prototypeValue._object()
|
obj.prototype = prototypeValue.object()
|
||||||
|
|
||||||
propertiesValue := call.Argument(1)
|
propertiesValue := call.Argument(1)
|
||||||
if propertiesValue.IsDefined() {
|
if propertiesValue.IsDefined() {
|
||||||
properties := call.runtime.toObject(propertiesValue)
|
properties := call.runtime.toObject(propertiesValue)
|
||||||
properties.enumerate(false, func(name string) bool {
|
properties.enumerate(false, func(name string) bool {
|
||||||
descriptor := toPropertyDescriptor(call.runtime, properties.get(name))
|
descriptor := toPropertyDescriptor(call.runtime, properties.get(name))
|
||||||
object.defineOwnProperty(name, descriptor, true)
|
obj.defineOwnProperty(name, descriptor, true)
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return toValue_object(object)
|
return objectValue(obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinObject_isExtensible(call FunctionCall) Value {
|
func builtinObjectIsExtensible(call FunctionCall) Value {
|
||||||
object := call.Argument(0)
|
val := call.Argument(0)
|
||||||
if object := object._object(); object != nil {
|
if obj := val.object(); obj != nil {
|
||||||
return toValue_bool(object.extensible)
|
return boolValue(obj.extensible)
|
||||||
}
|
}
|
||||||
panic(call.runtime.panicTypeError())
|
panic(call.runtime.panicTypeError("Object.IsExtensible is nil"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinObject_preventExtensions(call FunctionCall) Value {
|
func builtinObjectPreventExtensions(call FunctionCall) Value {
|
||||||
object := call.Argument(0)
|
val := call.Argument(0)
|
||||||
if object := object._object(); object != nil {
|
if obj := val.object(); obj != nil {
|
||||||
object.extensible = false
|
obj.extensible = false
|
||||||
} else {
|
return val
|
||||||
panic(call.runtime.panicTypeError())
|
|
||||||
}
|
}
|
||||||
return object
|
panic(call.runtime.panicTypeError("Object.PreventExtensions is nil"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinObject_isSealed(call FunctionCall) Value {
|
func builtinObjectIsSealed(call FunctionCall) Value {
|
||||||
object := call.Argument(0)
|
val := call.Argument(0)
|
||||||
if object := object._object(); object != nil {
|
if obj := val.object(); obj != nil {
|
||||||
if object.extensible {
|
if obj.extensible {
|
||||||
return toValue_bool(false)
|
return boolValue(false)
|
||||||
}
|
}
|
||||||
result := true
|
result := true
|
||||||
object.enumerate(true, func(name string) bool {
|
obj.enumerate(true, func(name string) bool {
|
||||||
property := object.getProperty(name)
|
prop := obj.getProperty(name)
|
||||||
if property.configurable() {
|
if prop.configurable() {
|
||||||
result = false
|
result = false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
return toValue_bool(result)
|
return boolValue(result)
|
||||||
}
|
}
|
||||||
panic(call.runtime.panicTypeError())
|
panic(call.runtime.panicTypeError("Object.IsSealed is nil"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinObject_seal(call FunctionCall) Value {
|
func builtinObjectSeal(call FunctionCall) Value {
|
||||||
object := call.Argument(0)
|
val := call.Argument(0)
|
||||||
if object := object._object(); object != nil {
|
if obj := val.object(); obj != nil {
|
||||||
object.enumerate(true, func(name string) bool {
|
obj.enumerate(true, func(name string) bool {
|
||||||
if property := object.getOwnProperty(name); nil != property && property.configurable() {
|
if prop := obj.getOwnProperty(name); nil != prop && prop.configurable() {
|
||||||
property.configureOff()
|
prop.configureOff()
|
||||||
object.defineOwnProperty(name, *property, true)
|
obj.defineOwnProperty(name, *prop, true)
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
object.extensible = false
|
obj.extensible = false
|
||||||
} else {
|
return val
|
||||||
panic(call.runtime.panicTypeError())
|
|
||||||
}
|
}
|
||||||
return object
|
panic(call.runtime.panicTypeError("Object.Seal is nil"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinObject_isFrozen(call FunctionCall) Value {
|
func builtinObjectIsFrozen(call FunctionCall) Value {
|
||||||
object := call.Argument(0)
|
val := call.Argument(0)
|
||||||
if object := object._object(); object != nil {
|
if obj := val.object(); obj != nil {
|
||||||
if object.extensible {
|
if obj.extensible {
|
||||||
return toValue_bool(false)
|
return boolValue(false)
|
||||||
}
|
}
|
||||||
result := true
|
result := true
|
||||||
object.enumerate(true, func(name string) bool {
|
obj.enumerate(true, func(name string) bool {
|
||||||
property := object.getProperty(name)
|
prop := obj.getProperty(name)
|
||||||
if property.configurable() || property.writable() {
|
if prop.configurable() || prop.writable() {
|
||||||
result = false
|
result = false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
return toValue_bool(result)
|
return boolValue(result)
|
||||||
}
|
}
|
||||||
panic(call.runtime.panicTypeError())
|
panic(call.runtime.panicTypeError("Object.IsFrozen is nil"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinObject_freeze(call FunctionCall) Value {
|
func builtinObjectFreeze(call FunctionCall) Value {
|
||||||
object := call.Argument(0)
|
val := call.Argument(0)
|
||||||
if object := object._object(); object != nil {
|
if obj := val.object(); obj != nil {
|
||||||
object.enumerate(true, func(name string) bool {
|
obj.enumerate(true, func(name string) bool {
|
||||||
if property, update := object.getOwnProperty(name), false; nil != property {
|
if prop, update := obj.getOwnProperty(name), false; nil != prop {
|
||||||
if property.isDataDescriptor() && property.writable() {
|
if prop.isDataDescriptor() && prop.writable() {
|
||||||
property.writeOff()
|
prop.writeOff()
|
||||||
update = true
|
update = true
|
||||||
}
|
}
|
||||||
if property.configurable() {
|
if prop.configurable() {
|
||||||
property.configureOff()
|
prop.configureOff()
|
||||||
update = true
|
update = true
|
||||||
}
|
}
|
||||||
if update {
|
if update {
|
||||||
object.defineOwnProperty(name, *property, true)
|
obj.defineOwnProperty(name, *prop, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
object.extensible = false
|
obj.extensible = false
|
||||||
} else {
|
return val
|
||||||
panic(call.runtime.panicTypeError())
|
|
||||||
}
|
}
|
||||||
return object
|
panic(call.runtime.panicTypeError("Object.Freeze is nil"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinObject_keys(call FunctionCall) Value {
|
func builtinObjectKeys(call FunctionCall) Value {
|
||||||
if object, keys := call.Argument(0)._object(), []Value(nil); nil != object {
|
if obj, keys := call.Argument(0).object(), []Value(nil); nil != obj {
|
||||||
object.enumerate(false, func(name string) bool {
|
obj.enumerate(false, func(name string) bool {
|
||||||
keys = append(keys, toValue_string(name))
|
keys = append(keys, stringValue(name))
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
return toValue_object(call.runtime.newArrayOf(keys))
|
return objectValue(call.runtime.newArrayOf(keys))
|
||||||
}
|
}
|
||||||
panic(call.runtime.panicTypeError())
|
panic(call.runtime.panicTypeError("Object.Keys is nil"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinObject_getOwnPropertyNames(call FunctionCall) Value {
|
func builtinObjectGetOwnPropertyNames(call FunctionCall) Value {
|
||||||
if object, propertyNames := call.Argument(0)._object(), []Value(nil); nil != object {
|
if obj, propertyNames := call.Argument(0).object(), []Value(nil); nil != obj {
|
||||||
object.enumerate(true, func(name string) bool {
|
obj.enumerate(true, func(name string) bool {
|
||||||
if object.hasOwnProperty(name) {
|
if obj.hasOwnProperty(name) {
|
||||||
propertyNames = append(propertyNames, toValue_string(name))
|
propertyNames = append(propertyNames, stringValue(name))
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
return toValue_object(call.runtime.newArrayOf(propertyNames))
|
return objectValue(call.runtime.newArrayOf(propertyNames))
|
||||||
}
|
}
|
||||||
panic(call.runtime.panicTypeError())
|
|
||||||
|
// Default to empty array for non object types.
|
||||||
|
return objectValue(call.runtime.newArray(0))
|
||||||
}
|
}
|
||||||
|
|
43
v1/vendor/github.com/robertkrimen/otto/builtin_regexp.go
generated
vendored
|
@ -9,22 +9,22 @@ import (
|
||||||
func builtinRegExp(call FunctionCall) Value {
|
func builtinRegExp(call FunctionCall) Value {
|
||||||
pattern := call.Argument(0)
|
pattern := call.Argument(0)
|
||||||
flags := call.Argument(1)
|
flags := call.Argument(1)
|
||||||
if object := pattern._object(); object != nil {
|
if obj := pattern.object(); obj != nil {
|
||||||
if object.class == classRegExp && flags.IsUndefined() {
|
if obj.class == classRegExpName && flags.IsUndefined() {
|
||||||
return pattern
|
return pattern
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return toValue_object(call.runtime.newRegExp(pattern, flags))
|
return objectValue(call.runtime.newRegExp(pattern, flags))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinNewRegExp(self *_object, argumentList []Value) Value {
|
func builtinNewRegExp(obj *object, argumentList []Value) Value {
|
||||||
return toValue_object(self.runtime.newRegExp(
|
return objectValue(obj.runtime.newRegExp(
|
||||||
valueOfArrayIndex(argumentList, 0),
|
valueOfArrayIndex(argumentList, 0),
|
||||||
valueOfArrayIndex(argumentList, 1),
|
valueOfArrayIndex(argumentList, 1),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinRegExp_toString(call FunctionCall) Value {
|
func builtinRegExpToString(call FunctionCall) Value {
|
||||||
thisObject := call.thisObject()
|
thisObject := call.thisObject()
|
||||||
source := thisObject.get("source").string()
|
source := thisObject.get("source").string()
|
||||||
flags := []byte{}
|
flags := []byte{}
|
||||||
|
@ -37,41 +37,47 @@ func builtinRegExp_toString(call FunctionCall) Value {
|
||||||
if thisObject.get("multiline").bool() {
|
if thisObject.get("multiline").bool() {
|
||||||
flags = append(flags, 'm')
|
flags = append(flags, 'm')
|
||||||
}
|
}
|
||||||
return toValue_string(fmt.Sprintf("/%s/%s", source, flags))
|
return stringValue(fmt.Sprintf("/%s/%s", source, flags))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinRegExp_exec(call FunctionCall) Value {
|
func builtinRegExpExec(call FunctionCall) Value {
|
||||||
thisObject := call.thisObject()
|
thisObject := call.thisObject()
|
||||||
target := call.Argument(0).string()
|
target := call.Argument(0).string()
|
||||||
match, result := execRegExp(thisObject, target)
|
match, result := execRegExp(thisObject, target)
|
||||||
if !match {
|
if !match {
|
||||||
return nullValue
|
return nullValue
|
||||||
}
|
}
|
||||||
return toValue_object(execResultToArray(call.runtime, target, result))
|
return objectValue(execResultToArray(call.runtime, target, result))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinRegExp_test(call FunctionCall) Value {
|
func builtinRegExpTest(call FunctionCall) Value {
|
||||||
thisObject := call.thisObject()
|
thisObject := call.thisObject()
|
||||||
target := call.Argument(0).string()
|
target := call.Argument(0).string()
|
||||||
match, result := execRegExp(thisObject, target)
|
match, result := execRegExp(thisObject, target)
|
||||||
|
|
||||||
if !match {
|
if !match {
|
||||||
return toValue_bool(match)
|
return boolValue(match)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Match extract and assign input, $_ and $1 -> $9 on global RegExp.
|
// Match extract and assign input, $_ and $1 -> $9 on global RegExp.
|
||||||
input := toValue_string(target)
|
input := stringValue(target)
|
||||||
call.runtime.global.RegExp.defineProperty("$_", input, 0100, false)
|
call.runtime.global.RegExp.defineProperty("$_", input, 0o100, false)
|
||||||
call.runtime.global.RegExp.defineProperty("input", input, 0100, false)
|
call.runtime.global.RegExp.defineProperty("input", input, 0o100, false)
|
||||||
|
|
||||||
var start int
|
var start int
|
||||||
n := 1
|
n := 1
|
||||||
re := call.runtime.global.RegExp
|
re := call.runtime.global.RegExp
|
||||||
|
empty := stringValue("")
|
||||||
for i, v := range result[2:] {
|
for i, v := range result[2:] {
|
||||||
if i%2 == 0 {
|
if i%2 == 0 {
|
||||||
start = v
|
start = v
|
||||||
} else {
|
} else {
|
||||||
re.defineProperty(fmt.Sprintf("$%d", n), toValue_string(target[start:v]), 0100, false)
|
if v == -1 {
|
||||||
|
// No match for this part.
|
||||||
|
re.defineProperty(fmt.Sprintf("$%d", n), empty, 0o100, false)
|
||||||
|
} else {
|
||||||
|
re.defineProperty(fmt.Sprintf("$%d", n), stringValue(target[start:v]), 0o100, false)
|
||||||
|
}
|
||||||
n++
|
n++
|
||||||
if n == 10 {
|
if n == 10 {
|
||||||
break
|
break
|
||||||
|
@ -81,16 +87,15 @@ func builtinRegExp_test(call FunctionCall) Value {
|
||||||
|
|
||||||
if n <= 9 {
|
if n <= 9 {
|
||||||
// Erase remaining.
|
// Erase remaining.
|
||||||
empty := toValue_string("")
|
|
||||||
for i := n; i <= 9; i++ {
|
for i := n; i <= 9; i++ {
|
||||||
re.defineProperty(fmt.Sprintf("$%d", i), empty, 0100, false)
|
re.defineProperty(fmt.Sprintf("$%d", i), empty, 0o100, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return toValue_bool(match)
|
return boolValue(match)
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinRegExp_compile(call FunctionCall) Value {
|
func builtinRegExpCompile(call FunctionCall) Value {
|
||||||
// This (useless) function is deprecated, but is here to provide some
|
// This (useless) function is deprecated, but is here to provide some
|
||||||
// semblance of compatibility.
|
// semblance of compatibility.
|
||||||
// Caveat emptor: it may not be around for long.
|
// Caveat emptor: it may not be around for long.
|
||||||
|
|
240
v1/vendor/github.com/robertkrimen/otto/builtin_string.go
generated
vendored
|
@ -13,62 +13,63 @@ import (
|
||||||
|
|
||||||
func stringValueFromStringArgumentList(argumentList []Value) Value {
|
func stringValueFromStringArgumentList(argumentList []Value) Value {
|
||||||
if len(argumentList) > 0 {
|
if len(argumentList) > 0 {
|
||||||
return toValue_string(argumentList[0].string())
|
return stringValue(argumentList[0].string())
|
||||||
}
|
}
|
||||||
return toValue_string("")
|
return stringValue("")
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinString(call FunctionCall) Value {
|
func builtinString(call FunctionCall) Value {
|
||||||
return stringValueFromStringArgumentList(call.ArgumentList)
|
return stringValueFromStringArgumentList(call.ArgumentList)
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinNewString(self *_object, argumentList []Value) Value {
|
func builtinNewString(obj *object, argumentList []Value) Value {
|
||||||
return toValue_object(self.runtime.newString(stringValueFromStringArgumentList(argumentList)))
|
return objectValue(obj.runtime.newString(stringValueFromStringArgumentList(argumentList)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinString_toString(call FunctionCall) Value {
|
func builtinStringToString(call FunctionCall) Value {
|
||||||
return call.thisClassObject(classString).primitiveValue()
|
return call.thisClassObject(classStringName).primitiveValue()
|
||||||
}
|
|
||||||
func builtinString_valueOf(call FunctionCall) Value {
|
|
||||||
return call.thisClassObject(classString).primitiveValue()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinString_fromCharCode(call FunctionCall) Value {
|
func builtinStringValueOf(call FunctionCall) Value {
|
||||||
|
return call.thisClassObject(classStringName).primitiveValue()
|
||||||
|
}
|
||||||
|
|
||||||
|
func builtinStringFromCharCode(call FunctionCall) Value {
|
||||||
chrList := make([]uint16, len(call.ArgumentList))
|
chrList := make([]uint16, len(call.ArgumentList))
|
||||||
for index, value := range call.ArgumentList {
|
for index, value := range call.ArgumentList {
|
||||||
chrList[index] = toUint16(value)
|
chrList[index] = toUint16(value)
|
||||||
}
|
}
|
||||||
return toValue_string16(chrList)
|
return string16Value(chrList)
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinString_charAt(call FunctionCall) Value {
|
func builtinStringCharAt(call FunctionCall) Value {
|
||||||
checkObjectCoercible(call.runtime, call.This)
|
checkObjectCoercible(call.runtime, call.This)
|
||||||
idx := int(call.Argument(0).number().int64)
|
idx := int(call.Argument(0).number().int64)
|
||||||
chr := stringAt(call.This._object().stringValue(), idx)
|
chr := stringAt(call.This.object().stringValue(), idx)
|
||||||
if chr == utf8.RuneError {
|
if chr == utf8.RuneError {
|
||||||
return toValue_string("")
|
return stringValue("")
|
||||||
}
|
}
|
||||||
return toValue_string(string(chr))
|
return stringValue(string(chr))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinString_charCodeAt(call FunctionCall) Value {
|
func builtinStringCharCodeAt(call FunctionCall) Value {
|
||||||
checkObjectCoercible(call.runtime, call.This)
|
checkObjectCoercible(call.runtime, call.This)
|
||||||
idx := int(call.Argument(0).number().int64)
|
idx := int(call.Argument(0).number().int64)
|
||||||
chr := stringAt(call.This._object().stringValue(), idx)
|
chr := stringAt(call.This.object().stringValue(), idx)
|
||||||
if chr == utf8.RuneError {
|
if chr == utf8.RuneError {
|
||||||
return NaNValue()
|
return NaNValue()
|
||||||
}
|
}
|
||||||
return toValue_uint16(uint16(chr))
|
return uint16Value(uint16(chr))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinString_concat(call FunctionCall) Value {
|
func builtinStringConcat(call FunctionCall) Value {
|
||||||
checkObjectCoercible(call.runtime, call.This)
|
checkObjectCoercible(call.runtime, call.This)
|
||||||
var value bytes.Buffer
|
var value bytes.Buffer
|
||||||
value.WriteString(call.This.string())
|
value.WriteString(call.This.string())
|
||||||
for _, item := range call.ArgumentList {
|
for _, item := range call.ArgumentList {
|
||||||
value.WriteString(item.string())
|
value.WriteString(item.string())
|
||||||
}
|
}
|
||||||
return toValue_string(value.String())
|
return stringValue(value.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
func lastIndexRune(s, substr string) int {
|
func lastIndexRune(s, substr string) int {
|
||||||
|
@ -89,44 +90,44 @@ func utf16Length(s string) int {
|
||||||
return len(utf16.Encode([]rune(s)))
|
return len(utf16.Encode([]rune(s)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinString_indexOf(call FunctionCall) Value {
|
func builtinStringIndexOf(call FunctionCall) Value {
|
||||||
checkObjectCoercible(call.runtime, call.This)
|
checkObjectCoercible(call.runtime, call.This)
|
||||||
value := call.This.string()
|
value := call.This.string()
|
||||||
target := call.Argument(0).string()
|
target := call.Argument(0).string()
|
||||||
if 2 > len(call.ArgumentList) {
|
if 2 > len(call.ArgumentList) {
|
||||||
return toValue_int(indexRune(value, target))
|
return intValue(indexRune(value, target))
|
||||||
}
|
}
|
||||||
start := toIntegerFloat(call.Argument(1))
|
start := toIntegerFloat(call.Argument(1))
|
||||||
if 0 > start {
|
if 0 > start {
|
||||||
start = 0
|
start = 0
|
||||||
} else if start >= float64(len(value)) {
|
} else if start >= float64(len(value)) {
|
||||||
if target == "" {
|
if target == "" {
|
||||||
return toValue_int(len(value))
|
return intValue(len(value))
|
||||||
}
|
}
|
||||||
return toValue_int(-1)
|
return intValue(-1)
|
||||||
}
|
}
|
||||||
index := indexRune(value[int(start):], target)
|
index := indexRune(value[int(start):], target)
|
||||||
if index >= 0 {
|
if index >= 0 {
|
||||||
index += int(start)
|
index += int(start)
|
||||||
}
|
}
|
||||||
return toValue_int(index)
|
return intValue(index)
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinString_lastIndexOf(call FunctionCall) Value {
|
func builtinStringLastIndexOf(call FunctionCall) Value {
|
||||||
checkObjectCoercible(call.runtime, call.This)
|
checkObjectCoercible(call.runtime, call.This)
|
||||||
value := call.This.string()
|
value := call.This.string()
|
||||||
target := call.Argument(0).string()
|
target := call.Argument(0).string()
|
||||||
if 2 > len(call.ArgumentList) || call.ArgumentList[1].IsUndefined() {
|
if 2 > len(call.ArgumentList) || call.ArgumentList[1].IsUndefined() {
|
||||||
return toValue_int(lastIndexRune(value, target))
|
return intValue(lastIndexRune(value, target))
|
||||||
}
|
}
|
||||||
length := len(value)
|
length := len(value)
|
||||||
if length == 0 {
|
if length == 0 {
|
||||||
return toValue_int(lastIndexRune(value, target))
|
return intValue(lastIndexRune(value, target))
|
||||||
}
|
}
|
||||||
start := call.ArgumentList[1].number()
|
start := call.ArgumentList[1].number()
|
||||||
if start.kind == numberInfinity { // FIXME
|
if start.kind == numberInfinity { // FIXME
|
||||||
// startNumber is infinity, so start is the end of string (start = length)
|
// startNumber is infinity, so start is the end of string (start = length)
|
||||||
return toValue_int(lastIndexRune(value, target))
|
return intValue(lastIndexRune(value, target))
|
||||||
}
|
}
|
||||||
if 0 > start.int64 {
|
if 0 > start.int64 {
|
||||||
start.int64 = 0
|
start.int64 = 0
|
||||||
|
@ -135,15 +136,15 @@ func builtinString_lastIndexOf(call FunctionCall) Value {
|
||||||
if end > length {
|
if end > length {
|
||||||
end = length
|
end = length
|
||||||
}
|
}
|
||||||
return toValue_int(lastIndexRune(value[:end], target))
|
return intValue(lastIndexRune(value[:end], target))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinString_match(call FunctionCall) Value {
|
func builtinStringMatch(call FunctionCall) Value {
|
||||||
checkObjectCoercible(call.runtime, call.This)
|
checkObjectCoercible(call.runtime, call.This)
|
||||||
target := call.This.string()
|
target := call.This.string()
|
||||||
matcherValue := call.Argument(0)
|
matcherValue := call.Argument(0)
|
||||||
matcher := matcherValue._object()
|
matcher := matcherValue.object()
|
||||||
if !matcherValue.IsObject() || matcher.class != classRegExp {
|
if !matcherValue.IsObject() || matcher.class != classRegExpName {
|
||||||
matcher = call.runtime.newRegExp(matcherValue, Value{})
|
matcher = call.runtime.newRegExp(matcherValue, Value{})
|
||||||
}
|
}
|
||||||
global := matcher.get("global").bool()
|
global := matcher.get("global").bool()
|
||||||
|
@ -152,34 +153,32 @@ func builtinString_match(call FunctionCall) Value {
|
||||||
if !match {
|
if !match {
|
||||||
return nullValue
|
return nullValue
|
||||||
}
|
}
|
||||||
return toValue_object(execResultToArray(call.runtime, target, result))
|
return objectValue(execResultToArray(call.runtime, target, result))
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
|
||||||
result := matcher.regExpValue().regularExpression.FindAllStringIndex(target, -1)
|
result := matcher.regExpValue().regularExpression.FindAllStringIndex(target, -1)
|
||||||
if result == nil {
|
if result == nil {
|
||||||
matcher.put("lastIndex", toValue_int(0), true)
|
matcher.put("lastIndex", intValue(0), true)
|
||||||
return Value{} // !match
|
return Value{} // !match
|
||||||
}
|
}
|
||||||
matchCount := len(result)
|
matchCount := len(result)
|
||||||
valueArray := make([]Value, matchCount)
|
valueArray := make([]Value, matchCount)
|
||||||
for index := 0; index < matchCount; index++ {
|
for index := 0; index < matchCount; index++ {
|
||||||
valueArray[index] = toValue_string(target[result[index][0]:result[index][1]])
|
valueArray[index] = stringValue(target[result[index][0]:result[index][1]])
|
||||||
}
|
|
||||||
matcher.put("lastIndex", toValue_int(result[matchCount-1][1]), true)
|
|
||||||
return toValue_object(call.runtime.newArrayOf(valueArray))
|
|
||||||
}
|
}
|
||||||
|
matcher.put("lastIndex", intValue(result[matchCount-1][1]), true)
|
||||||
|
return objectValue(call.runtime.newArrayOf(valueArray))
|
||||||
}
|
}
|
||||||
|
|
||||||
var builtinString_replace_Regexp = regexp.MustCompile("\\$(?:[\\$\\&\\'\\`1-9]|0[1-9]|[1-9][0-9])")
|
var builtinStringReplaceRegexp = regexp.MustCompile("\\$(?:[\\$\\&\\'\\`1-9]|0[1-9]|[1-9][0-9])")
|
||||||
|
|
||||||
func builtinString_findAndReplaceString(input []byte, lastIndex int, match []int, target []byte, replaceValue []byte) (output []byte) {
|
func builtinStringFindAndReplaceString(input []byte, lastIndex int, match []int, target []byte, replaceValue []byte) []byte {
|
||||||
matchCount := len(match) / 2
|
matchCount := len(match) / 2
|
||||||
output = input
|
output := input
|
||||||
if match[0] != lastIndex {
|
if match[0] != lastIndex {
|
||||||
output = append(output, target[lastIndex:match[0]]...)
|
output = append(output, target[lastIndex:match[0]]...)
|
||||||
}
|
}
|
||||||
replacement := builtinString_replace_Regexp.ReplaceAllFunc(replaceValue, func(part []byte) []byte {
|
replacement := builtinStringReplaceRegexp.ReplaceAllFunc(replaceValue, func(part []byte) []byte {
|
||||||
// TODO Check if match[0] or match[1] can be -1 in this scenario
|
// TODO Check if match[0] or match[1] can be -1 in this scenario
|
||||||
switch part[1] {
|
switch part[1] {
|
||||||
case '$':
|
case '$':
|
||||||
|
@ -193,37 +192,38 @@ func builtinString_findAndReplaceString(input []byte, lastIndex int, match []int
|
||||||
}
|
}
|
||||||
matchNumberParse, err := strconv.ParseInt(string(part[1:]), 10, 64)
|
matchNumberParse, err := strconv.ParseInt(string(part[1:]), 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return []byte{}
|
return nil
|
||||||
}
|
}
|
||||||
matchNumber := int(matchNumberParse)
|
matchNumber := int(matchNumberParse)
|
||||||
if matchNumber >= matchCount {
|
if matchNumber >= matchCount {
|
||||||
return []byte{}
|
return nil
|
||||||
}
|
}
|
||||||
offset := 2 * matchNumber
|
offset := 2 * matchNumber
|
||||||
if match[offset] != -1 {
|
if match[offset] != -1 {
|
||||||
return target[match[offset]:match[offset+1]]
|
return target[match[offset]:match[offset+1]]
|
||||||
}
|
}
|
||||||
return []byte{} // The empty string
|
return nil // The empty string
|
||||||
})
|
})
|
||||||
output = append(output, replacement...)
|
|
||||||
return output
|
return append(output, replacement...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinString_replace(call FunctionCall) Value {
|
func builtinStringReplace(call FunctionCall) Value {
|
||||||
checkObjectCoercible(call.runtime, call.This)
|
checkObjectCoercible(call.runtime, call.This)
|
||||||
target := []byte(call.This.string())
|
target := []byte(call.This.string())
|
||||||
searchValue := call.Argument(0)
|
searchValue := call.Argument(0)
|
||||||
searchObject := searchValue._object()
|
searchObject := searchValue.object()
|
||||||
|
|
||||||
// TODO If a capture is -1?
|
// TODO If a capture is -1?
|
||||||
var search *regexp.Regexp
|
var search *regexp.Regexp
|
||||||
global := false
|
global := false
|
||||||
find := 1
|
find := 1
|
||||||
if searchValue.IsObject() && searchObject.class == classRegExp {
|
if searchValue.IsObject() && searchObject.class == classRegExpName {
|
||||||
regExp := searchObject.regExpValue()
|
regExp := searchObject.regExpValue()
|
||||||
search = regExp.regularExpression
|
search = regExp.regularExpression
|
||||||
if regExp.global {
|
if regExp.global {
|
||||||
find = -1
|
find = -1
|
||||||
|
global = true
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
search = regexp.MustCompile(regexp.QuoteMeta(searchValue.string()))
|
search = regexp.MustCompile(regexp.QuoteMeta(searchValue.string()))
|
||||||
|
@ -231,17 +231,15 @@ func builtinString_replace(call FunctionCall) Value {
|
||||||
|
|
||||||
found := search.FindAllSubmatchIndex(target, find)
|
found := search.FindAllSubmatchIndex(target, find)
|
||||||
if found == nil {
|
if found == nil {
|
||||||
return toValue_string(string(target)) // !match
|
return stringValue(string(target)) // !match
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
|
||||||
lastIndex := 0
|
lastIndex := 0
|
||||||
result := []byte{}
|
result := []byte{}
|
||||||
|
|
||||||
replaceValue := call.Argument(1)
|
replaceValue := call.Argument(1)
|
||||||
if replaceValue.isCallable() {
|
if replaceValue.isCallable() {
|
||||||
target := string(target)
|
target := string(target)
|
||||||
replace := replaceValue._object()
|
replace := replaceValue.object()
|
||||||
for _, match := range found {
|
for _, match := range found {
|
||||||
if match[0] != lastIndex {
|
if match[0] != lastIndex {
|
||||||
result = append(result, target[lastIndex:match[0]]...)
|
result = append(result, target[lastIndex:match[0]]...)
|
||||||
|
@ -251,13 +249,13 @@ func builtinString_replace(call FunctionCall) Value {
|
||||||
for index := 0; index < matchCount; index++ {
|
for index := 0; index < matchCount; index++ {
|
||||||
offset := 2 * index
|
offset := 2 * index
|
||||||
if match[offset] != -1 {
|
if match[offset] != -1 {
|
||||||
argumentList[index] = toValue_string(target[match[offset]:match[offset+1]])
|
argumentList[index] = stringValue(target[match[offset]:match[offset+1]])
|
||||||
} else {
|
} else {
|
||||||
argumentList[index] = Value{}
|
argumentList[index] = Value{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
argumentList[matchCount+0] = toValue_int(match[0])
|
argumentList[matchCount+0] = intValue(match[0])
|
||||||
argumentList[matchCount+1] = toValue_string(target)
|
argumentList[matchCount+1] = stringValue(target)
|
||||||
replacement := replace.call(Value{}, argumentList, false, nativeFrame).string()
|
replacement := replace.call(Value{}, argumentList, false, nativeFrame).string()
|
||||||
result = append(result, []byte(replacement)...)
|
result = append(result, []byte(replacement)...)
|
||||||
lastIndex = match[1]
|
lastIndex = match[1]
|
||||||
|
@ -265,7 +263,7 @@ func builtinString_replace(call FunctionCall) Value {
|
||||||
} else {
|
} else {
|
||||||
replace := []byte(replaceValue.string())
|
replace := []byte(replaceValue.string())
|
||||||
for _, match := range found {
|
for _, match := range found {
|
||||||
result = builtinString_findAndReplaceString(result, lastIndex, match, target, replace)
|
result = builtinStringFindAndReplaceString(result, lastIndex, match, target, replace)
|
||||||
lastIndex = match[1]
|
lastIndex = match[1]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -275,29 +273,28 @@ func builtinString_replace(call FunctionCall) Value {
|
||||||
}
|
}
|
||||||
|
|
||||||
if global && searchObject != nil {
|
if global && searchObject != nil {
|
||||||
searchObject.put("lastIndex", toValue_int(lastIndex), true)
|
searchObject.put("lastIndex", intValue(lastIndex), true)
|
||||||
}
|
}
|
||||||
|
|
||||||
return toValue_string(string(result))
|
return stringValue(string(result))
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinString_search(call FunctionCall) Value {
|
func builtinStringSearch(call FunctionCall) Value {
|
||||||
checkObjectCoercible(call.runtime, call.This)
|
checkObjectCoercible(call.runtime, call.This)
|
||||||
target := call.This.string()
|
target := call.This.string()
|
||||||
searchValue := call.Argument(0)
|
searchValue := call.Argument(0)
|
||||||
search := searchValue._object()
|
search := searchValue.object()
|
||||||
if !searchValue.IsObject() || search.class != classRegExp {
|
if !searchValue.IsObject() || search.class != classRegExpName {
|
||||||
search = call.runtime.newRegExp(searchValue, Value{})
|
search = call.runtime.newRegExp(searchValue, Value{})
|
||||||
}
|
}
|
||||||
result := search.regExpValue().regularExpression.FindStringIndex(target)
|
result := search.regExpValue().regularExpression.FindStringIndex(target)
|
||||||
if result == nil {
|
if result == nil {
|
||||||
return toValue_int(-1)
|
return intValue(-1)
|
||||||
}
|
}
|
||||||
return toValue_int(result[0])
|
return intValue(result[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinString_split(call FunctionCall) Value {
|
func builtinStringSplit(call FunctionCall) Value {
|
||||||
checkObjectCoercible(call.runtime, call.This)
|
checkObjectCoercible(call.runtime, call.This)
|
||||||
target := call.This.string()
|
target := call.This.string()
|
||||||
|
|
||||||
|
@ -309,16 +306,16 @@ func builtinString_split(call FunctionCall) Value {
|
||||||
}
|
}
|
||||||
|
|
||||||
if limit == 0 {
|
if limit == 0 {
|
||||||
return toValue_object(call.runtime.newArray(0))
|
return objectValue(call.runtime.newArray(0))
|
||||||
}
|
}
|
||||||
|
|
||||||
if separatorValue.IsUndefined() {
|
if separatorValue.IsUndefined() {
|
||||||
return toValue_object(call.runtime.newArrayOf([]Value{toValue_string(target)}))
|
return objectValue(call.runtime.newArrayOf([]Value{stringValue(target)}))
|
||||||
}
|
}
|
||||||
|
|
||||||
if separatorValue.isRegExp() {
|
if separatorValue.isRegExp() {
|
||||||
targetLength := len(target)
|
targetLength := len(target)
|
||||||
search := separatorValue._object().regExpValue().regularExpression
|
search := separatorValue.object().regExpValue().regularExpression
|
||||||
valueArray := []Value{}
|
valueArray := []Value{}
|
||||||
result := search.FindAllStringSubmatchIndex(target, -1)
|
result := search.FindAllStringSubmatchIndex(target, -1)
|
||||||
lastIndex := 0
|
lastIndex := 0
|
||||||
|
@ -333,11 +330,11 @@ func builtinString_split(call FunctionCall) Value {
|
||||||
}
|
}
|
||||||
|
|
||||||
if lastIndex != match[0] {
|
if lastIndex != match[0] {
|
||||||
valueArray = append(valueArray, toValue_string(target[lastIndex:match[0]]))
|
valueArray = append(valueArray, stringValue(target[lastIndex:match[0]]))
|
||||||
found++
|
found++
|
||||||
} else if lastIndex == match[0] {
|
} else if lastIndex == match[0] {
|
||||||
if lastIndex != -1 {
|
if lastIndex != -1 {
|
||||||
valueArray = append(valueArray, toValue_string(""))
|
valueArray = append(valueArray, stringValue(""))
|
||||||
found++
|
found++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -352,7 +349,7 @@ func builtinString_split(call FunctionCall) Value {
|
||||||
offset := index * 2
|
offset := index * 2
|
||||||
value := Value{}
|
value := Value{}
|
||||||
if match[offset] != -1 {
|
if match[offset] != -1 {
|
||||||
value = toValue_string(target[match[offset]:match[offset+1]])
|
value = stringValue(target[match[offset]:match[offset+1]])
|
||||||
}
|
}
|
||||||
valueArray = append(valueArray, value)
|
valueArray = append(valueArray, value)
|
||||||
found++
|
found++
|
||||||
|
@ -364,14 +361,14 @@ func builtinString_split(call FunctionCall) Value {
|
||||||
|
|
||||||
if found != limit {
|
if found != limit {
|
||||||
if lastIndex != targetLength {
|
if lastIndex != targetLength {
|
||||||
valueArray = append(valueArray, toValue_string(target[lastIndex:targetLength]))
|
valueArray = append(valueArray, stringValue(target[lastIndex:targetLength]))
|
||||||
} else {
|
} else {
|
||||||
valueArray = append(valueArray, toValue_string(""))
|
valueArray = append(valueArray, stringValue(""))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RETURN:
|
RETURN:
|
||||||
return toValue_object(call.runtime.newArrayOf(valueArray))
|
return objectValue(call.runtime.newArrayOf(valueArray))
|
||||||
} else {
|
} else {
|
||||||
separator := separatorValue.string()
|
separator := separatorValue.string()
|
||||||
|
|
||||||
|
@ -390,26 +387,26 @@ func builtinString_split(call FunctionCall) Value {
|
||||||
|
|
||||||
valueArray := make([]Value, len(split))
|
valueArray := make([]Value, len(split))
|
||||||
for index, value := range split {
|
for index, value := range split {
|
||||||
valueArray[index] = toValue_string(value)
|
valueArray[index] = stringValue(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
return toValue_object(call.runtime.newArrayOf(valueArray))
|
return objectValue(call.runtime.newArrayOf(valueArray))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinString_slice(call FunctionCall) Value {
|
func builtinStringSlice(call FunctionCall) Value {
|
||||||
checkObjectCoercible(call.runtime, call.This)
|
checkObjectCoercible(call.runtime, call.This)
|
||||||
target := call.This.string()
|
target := call.This.string()
|
||||||
|
|
||||||
length := int64(len(target))
|
length := int64(len(target))
|
||||||
start, end := rangeStartEnd(call.ArgumentList, length, false)
|
start, end := rangeStartEnd(call.ArgumentList, length, false)
|
||||||
if end-start <= 0 {
|
if end-start <= 0 {
|
||||||
return toValue_string("")
|
return stringValue("")
|
||||||
}
|
}
|
||||||
return toValue_string(string(target[start:end]))
|
return stringValue(target[start:end])
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinString_substring(call FunctionCall) Value {
|
func builtinStringSubstring(call FunctionCall) Value {
|
||||||
checkObjectCoercible(call.runtime, call.This)
|
checkObjectCoercible(call.runtime, call.This)
|
||||||
target := []rune(call.This.string())
|
target := []rune(call.This.string())
|
||||||
|
|
||||||
|
@ -418,21 +415,21 @@ func builtinString_substring(call FunctionCall) Value {
|
||||||
if start > end {
|
if start > end {
|
||||||
start, end = end, start
|
start, end = end, start
|
||||||
}
|
}
|
||||||
return toValue_string(string(target[start:end]))
|
return stringValue(string(target[start:end]))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinString_substr(call FunctionCall) Value {
|
func builtinStringSubstr(call FunctionCall) Value {
|
||||||
target := []rune(call.This.string())
|
target := []rune(call.This.string())
|
||||||
|
|
||||||
size := int64(len(target))
|
size := int64(len(target))
|
||||||
start, length := rangeStartLength(call.ArgumentList, size)
|
start, length := rangeStartLength(call.ArgumentList, size)
|
||||||
|
|
||||||
if start >= size {
|
if start >= size {
|
||||||
return toValue_string("")
|
return stringValue("")
|
||||||
}
|
}
|
||||||
|
|
||||||
if length <= 0 {
|
if length <= 0 {
|
||||||
return toValue_string("")
|
return stringValue("")
|
||||||
}
|
}
|
||||||
|
|
||||||
if start+length >= size {
|
if start+length >= size {
|
||||||
|
@ -443,66 +440,69 @@ func builtinString_substr(call FunctionCall) Value {
|
||||||
length = size - start
|
length = size - start
|
||||||
}
|
}
|
||||||
|
|
||||||
return toValue_string(string(target[start : start+length]))
|
return stringValue(string(target[start : start+length]))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinString_toLowerCase(call FunctionCall) Value {
|
func builtinStringStartsWith(call FunctionCall) Value {
|
||||||
checkObjectCoercible(call.runtime, call.This)
|
checkObjectCoercible(call.runtime, call.This)
|
||||||
return toValue_string(strings.ToLower(call.This.string()))
|
target := call.This.string()
|
||||||
|
search := call.Argument(0).string()
|
||||||
|
length := len(search)
|
||||||
|
if length > len(target) {
|
||||||
|
return boolValue(false)
|
||||||
|
}
|
||||||
|
return boolValue(target[:length] == search)
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinString_toUpperCase(call FunctionCall) Value {
|
func builtinStringToLowerCase(call FunctionCall) Value {
|
||||||
checkObjectCoercible(call.runtime, call.This)
|
checkObjectCoercible(call.runtime, call.This)
|
||||||
return toValue_string(strings.ToUpper(call.This.string()))
|
return stringValue(strings.ToLower(call.This.string()))
|
||||||
}
|
}
|
||||||
|
|
||||||
// 7.2 Table 2 — Whitespace Characters & 7.3 Table 3 - Line Terminator Characters
|
func builtinStringToUpperCase(call FunctionCall) Value {
|
||||||
const builtinString_trim_whitespace = "\u0009\u000A\u000B\u000C\u000D\u0020\u00A0\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF"
|
checkObjectCoercible(call.runtime, call.This)
|
||||||
|
return stringValue(strings.ToUpper(call.This.string()))
|
||||||
|
}
|
||||||
|
|
||||||
func builtinString_trim(call FunctionCall) Value {
|
// 7.2 Table 2 — Whitespace Characters & 7.3 Table 3 - Line Terminator Characters.
|
||||||
|
const builtinStringTrimWhitespace = "\u0009\u000A\u000B\u000C\u000D\u0020\u00A0\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF"
|
||||||
|
|
||||||
|
func builtinStringTrim(call FunctionCall) Value {
|
||||||
checkObjectCoercible(call.runtime, call.This)
|
checkObjectCoercible(call.runtime, call.This)
|
||||||
return toValue(strings.Trim(call.This.string(),
|
return toValue(strings.Trim(call.This.string(),
|
||||||
builtinString_trim_whitespace))
|
builtinStringTrimWhitespace))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mozilla extension, not ECMAScript 5
|
// Mozilla extension, not ECMAScript 5.
|
||||||
func builtinString_trimLeft(call FunctionCall) Value {
|
func builtinStringTrimLeft(call FunctionCall) Value {
|
||||||
checkObjectCoercible(call.runtime, call.This)
|
checkObjectCoercible(call.runtime, call.This)
|
||||||
return toValue(strings.TrimLeft(call.This.string(),
|
return toValue(strings.TrimLeft(call.This.string(),
|
||||||
builtinString_trim_whitespace))
|
builtinStringTrimWhitespace))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mozilla extension, not ECMAScript 5
|
// Mozilla extension, not ECMAScript 5.
|
||||||
func builtinString_trimRight(call FunctionCall) Value {
|
func builtinStringTrimRight(call FunctionCall) Value {
|
||||||
checkObjectCoercible(call.runtime, call.This)
|
checkObjectCoercible(call.runtime, call.This)
|
||||||
return toValue(strings.TrimRight(call.This.string(),
|
return toValue(strings.TrimRight(call.This.string(),
|
||||||
builtinString_trim_whitespace))
|
builtinStringTrimWhitespace))
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinString_localeCompare(call FunctionCall) Value {
|
func builtinStringLocaleCompare(call FunctionCall) Value {
|
||||||
checkObjectCoercible(call.runtime, call.This)
|
checkObjectCoercible(call.runtime, call.This)
|
||||||
this := call.This.string()
|
this := call.This.string() //nolint: ifshort
|
||||||
that := call.Argument(0).string()
|
that := call.Argument(0).string()
|
||||||
if this < that {
|
if this < that {
|
||||||
return toValue_int(-1)
|
return intValue(-1)
|
||||||
} else if this == that {
|
} else if this == that {
|
||||||
return toValue_int(0)
|
return intValue(0)
|
||||||
}
|
}
|
||||||
return toValue_int(1)
|
return intValue(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
func builtinStringToLocaleLowerCase(call FunctionCall) Value {
|
||||||
An alternate version of String.trim
|
return builtinStringToLowerCase(call)
|
||||||
func builtinString_trim(call FunctionCall) Value {
|
|
||||||
checkObjectCoercible(call.This)
|
|
||||||
return toValue_string(strings.TrimFunc(call.string(.This), isWhiteSpaceOrLineTerminator))
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
func builtinString_toLocaleLowerCase(call FunctionCall) Value {
|
|
||||||
return builtinString_toLowerCase(call)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinString_toLocaleUpperCase(call FunctionCall) Value {
|
func builtinStringToLocaleUpperCase(call FunctionCall) Value {
|
||||||
return builtinString_toUpperCase(call)
|
return builtinStringToUpperCase(call)
|
||||||
}
|
}
|
||||||
|
|
183
v1/vendor/github.com/robertkrimen/otto/clone.go
generated
vendored
|
@ -4,158 +4,157 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
type _clone struct {
|
type cloner struct {
|
||||||
runtime *_runtime
|
runtime *runtime
|
||||||
_object map[*_object]*_object
|
obj map[*object]*object
|
||||||
_objectStash map[*_objectStash]*_objectStash
|
objectstash map[*objectStash]*objectStash
|
||||||
_dclStash map[*_dclStash]*_dclStash
|
dclstash map[*dclStash]*dclStash
|
||||||
_fnStash map[*_fnStash]*_fnStash
|
fnstash map[*fnStash]*fnStash
|
||||||
}
|
}
|
||||||
|
|
||||||
func (in *_runtime) clone() *_runtime {
|
func (rt *runtime) clone() *runtime {
|
||||||
in.lck.Lock()
|
rt.lck.Lock()
|
||||||
defer in.lck.Unlock()
|
defer rt.lck.Unlock()
|
||||||
|
|
||||||
out := &_runtime{
|
out := &runtime{
|
||||||
debugger: in.debugger,
|
debugger: rt.debugger,
|
||||||
random: in.random,
|
random: rt.random,
|
||||||
stackLimit: in.stackLimit,
|
stackLimit: rt.stackLimit,
|
||||||
traceLimit: in.traceLimit,
|
traceLimit: rt.traceLimit,
|
||||||
}
|
}
|
||||||
|
|
||||||
clone := _clone{
|
c := cloner{
|
||||||
runtime: out,
|
runtime: out,
|
||||||
_object: make(map[*_object]*_object),
|
obj: make(map[*object]*object),
|
||||||
_objectStash: make(map[*_objectStash]*_objectStash),
|
objectstash: make(map[*objectStash]*objectStash),
|
||||||
_dclStash: make(map[*_dclStash]*_dclStash),
|
dclstash: make(map[*dclStash]*dclStash),
|
||||||
_fnStash: make(map[*_fnStash]*_fnStash),
|
fnstash: make(map[*fnStash]*fnStash),
|
||||||
}
|
}
|
||||||
|
|
||||||
globalObject := clone.object(in.globalObject)
|
globalObject := c.object(rt.globalObject)
|
||||||
out.globalStash = out.newObjectStash(globalObject, nil)
|
out.globalStash = out.newObjectStash(globalObject, nil)
|
||||||
out.globalObject = globalObject
|
out.globalObject = globalObject
|
||||||
out.global = _global{
|
out.global = global{
|
||||||
clone.object(in.global.Object),
|
c.object(rt.global.Object),
|
||||||
clone.object(in.global.Function),
|
c.object(rt.global.Function),
|
||||||
clone.object(in.global.Array),
|
c.object(rt.global.Array),
|
||||||
clone.object(in.global.String),
|
c.object(rt.global.String),
|
||||||
clone.object(in.global.Boolean),
|
c.object(rt.global.Boolean),
|
||||||
clone.object(in.global.Number),
|
c.object(rt.global.Number),
|
||||||
clone.object(in.global.Math),
|
c.object(rt.global.Math),
|
||||||
clone.object(in.global.Date),
|
c.object(rt.global.Date),
|
||||||
clone.object(in.global.RegExp),
|
c.object(rt.global.RegExp),
|
||||||
clone.object(in.global.Error),
|
c.object(rt.global.Error),
|
||||||
clone.object(in.global.EvalError),
|
c.object(rt.global.EvalError),
|
||||||
clone.object(in.global.TypeError),
|
c.object(rt.global.TypeError),
|
||||||
clone.object(in.global.RangeError),
|
c.object(rt.global.RangeError),
|
||||||
clone.object(in.global.ReferenceError),
|
c.object(rt.global.ReferenceError),
|
||||||
clone.object(in.global.SyntaxError),
|
c.object(rt.global.SyntaxError),
|
||||||
clone.object(in.global.URIError),
|
c.object(rt.global.URIError),
|
||||||
clone.object(in.global.JSON),
|
c.object(rt.global.JSON),
|
||||||
|
|
||||||
clone.object(in.global.ObjectPrototype),
|
c.object(rt.global.ObjectPrototype),
|
||||||
clone.object(in.global.FunctionPrototype),
|
c.object(rt.global.FunctionPrototype),
|
||||||
clone.object(in.global.ArrayPrototype),
|
c.object(rt.global.ArrayPrototype),
|
||||||
clone.object(in.global.StringPrototype),
|
c.object(rt.global.StringPrototype),
|
||||||
clone.object(in.global.BooleanPrototype),
|
c.object(rt.global.BooleanPrototype),
|
||||||
clone.object(in.global.NumberPrototype),
|
c.object(rt.global.NumberPrototype),
|
||||||
clone.object(in.global.DatePrototype),
|
c.object(rt.global.DatePrototype),
|
||||||
clone.object(in.global.RegExpPrototype),
|
c.object(rt.global.RegExpPrototype),
|
||||||
clone.object(in.global.ErrorPrototype),
|
c.object(rt.global.ErrorPrototype),
|
||||||
clone.object(in.global.EvalErrorPrototype),
|
c.object(rt.global.EvalErrorPrototype),
|
||||||
clone.object(in.global.TypeErrorPrototype),
|
c.object(rt.global.TypeErrorPrototype),
|
||||||
clone.object(in.global.RangeErrorPrototype),
|
c.object(rt.global.RangeErrorPrototype),
|
||||||
clone.object(in.global.ReferenceErrorPrototype),
|
c.object(rt.global.ReferenceErrorPrototype),
|
||||||
clone.object(in.global.SyntaxErrorPrototype),
|
c.object(rt.global.SyntaxErrorPrototype),
|
||||||
clone.object(in.global.URIErrorPrototype),
|
c.object(rt.global.URIErrorPrototype),
|
||||||
}
|
}
|
||||||
|
|
||||||
out.eval = out.globalObject.property["eval"].value.(Value).value.(*_object)
|
out.eval = out.globalObject.property["eval"].value.(Value).value.(*object)
|
||||||
out.globalObject.prototype = out.global.ObjectPrototype
|
out.globalObject.prototype = out.global.ObjectPrototype
|
||||||
|
|
||||||
// Not sure if this is necessary, but give some help to the GC
|
// Not sure if this is necessary, but give some help to the GC
|
||||||
clone.runtime = nil
|
c.runtime = nil
|
||||||
clone._object = nil
|
c.obj = nil
|
||||||
clone._objectStash = nil
|
c.objectstash = nil
|
||||||
clone._dclStash = nil
|
c.dclstash = nil
|
||||||
clone._fnStash = nil
|
c.fnstash = nil
|
||||||
|
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
func (clone *_clone) object(in *_object) *_object {
|
func (c *cloner) object(in *object) *object {
|
||||||
if out, exists := clone._object[in]; exists {
|
if out, exists := c.obj[in]; exists {
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
out := &_object{}
|
out := &object{}
|
||||||
clone._object[in] = out
|
c.obj[in] = out
|
||||||
return in.objectClass.clone(in, out, clone)
|
return in.objectClass.clone(in, out, c)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (clone *_clone) dclStash(in *_dclStash) (*_dclStash, bool) {
|
func (c *cloner) dclStash(in *dclStash) (*dclStash, bool) {
|
||||||
if out, exists := clone._dclStash[in]; exists {
|
if out, exists := c.dclstash[in]; exists {
|
||||||
return out, true
|
return out, true
|
||||||
}
|
}
|
||||||
out := &_dclStash{}
|
out := &dclStash{}
|
||||||
clone._dclStash[in] = out
|
c.dclstash[in] = out
|
||||||
return out, false
|
return out, false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (clone *_clone) objectStash(in *_objectStash) (*_objectStash, bool) {
|
func (c *cloner) objectStash(in *objectStash) (*objectStash, bool) {
|
||||||
if out, exists := clone._objectStash[in]; exists {
|
if out, exists := c.objectstash[in]; exists {
|
||||||
return out, true
|
return out, true
|
||||||
}
|
}
|
||||||
out := &_objectStash{}
|
out := &objectStash{}
|
||||||
clone._objectStash[in] = out
|
c.objectstash[in] = out
|
||||||
return out, false
|
return out, false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (clone *_clone) fnStash(in *_fnStash) (*_fnStash, bool) {
|
func (c *cloner) fnStash(in *fnStash) (*fnStash, bool) {
|
||||||
if out, exists := clone._fnStash[in]; exists {
|
if out, exists := c.fnstash[in]; exists {
|
||||||
return out, true
|
return out, true
|
||||||
}
|
}
|
||||||
out := &_fnStash{}
|
out := &fnStash{}
|
||||||
clone._fnStash[in] = out
|
c.fnstash[in] = out
|
||||||
return out, false
|
return out, false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (clone *_clone) value(in Value) Value {
|
func (c *cloner) value(in Value) Value {
|
||||||
out := in
|
out := in
|
||||||
switch value := in.value.(type) {
|
if value, ok := in.value.(*object); ok {
|
||||||
case *_object:
|
out.value = c.object(value)
|
||||||
out.value = clone.object(value)
|
|
||||||
}
|
}
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
func (clone *_clone) valueArray(in []Value) []Value {
|
func (c *cloner) valueArray(in []Value) []Value {
|
||||||
out := make([]Value, len(in))
|
out := make([]Value, len(in))
|
||||||
for index, value := range in {
|
for index, value := range in {
|
||||||
out[index] = clone.value(value)
|
out[index] = c.value(value)
|
||||||
}
|
}
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
func (clone *_clone) stash(in _stash) _stash {
|
func (c *cloner) stash(in stasher) stasher {
|
||||||
if in == nil {
|
if in == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return in.clone(clone)
|
return in.clone(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (clone *_clone) property(in _property) _property {
|
func (c *cloner) property(in property) property {
|
||||||
out := in
|
out := in
|
||||||
|
|
||||||
switch value := in.value.(type) {
|
switch value := in.value.(type) {
|
||||||
case Value:
|
case Value:
|
||||||
out.value = clone.value(value)
|
out.value = c.value(value)
|
||||||
case _propertyGetSet:
|
case propertyGetSet:
|
||||||
p := _propertyGetSet{}
|
p := propertyGetSet{}
|
||||||
if value[0] != nil {
|
if value[0] != nil {
|
||||||
p[0] = clone.object(value[0])
|
p[0] = c.object(value[0])
|
||||||
}
|
}
|
||||||
if value[1] != nil {
|
if value[1] != nil {
|
||||||
p[1] = clone.object(value[1])
|
p[1] = c.object(value[1])
|
||||||
}
|
}
|
||||||
out.value = p
|
out.value = p
|
||||||
default:
|
default:
|
||||||
|
@ -165,8 +164,8 @@ func (clone *_clone) property(in _property) _property {
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
func (clone *_clone) dclProperty(in _dclProperty) _dclProperty {
|
func (c *cloner) dclProperty(in dclProperty) dclProperty {
|
||||||
out := in
|
out := in
|
||||||
out.value = clone.value(in.value)
|
out.value = c.value(in.value)
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
9
v1/vendor/github.com/robertkrimen/otto/cmpl.go
generated
vendored
|
@ -5,14 +5,7 @@ import (
|
||||||
"github.com/robertkrimen/otto/file"
|
"github.com/robertkrimen/otto/file"
|
||||||
)
|
)
|
||||||
|
|
||||||
type _compiler struct {
|
type compiler struct {
|
||||||
file *file.File
|
file *file.File
|
||||||
program *ast.Program
|
program *ast.Program
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cmpl *_compiler) parse() *_nodeProgram {
|
|
||||||
if cmpl.program != nil {
|
|
||||||
cmpl.file = cmpl.program.File
|
|
||||||
}
|
|
||||||
return cmpl._parse(cmpl.program)
|
|
||||||
}
|
|
||||||
|
|
50
v1/vendor/github.com/robertkrimen/otto/cmpl_evaluate.go
generated
vendored
|
@ -4,20 +4,18 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (self *_runtime) cmpl_evaluate_nodeProgram(node *_nodeProgram, eval bool) Value {
|
func (rt *runtime) cmplEvaluateNodeProgram(node *nodeProgram, eval bool) Value {
|
||||||
if !eval {
|
if !eval {
|
||||||
self.enterGlobalScope()
|
rt.enterGlobalScope()
|
||||||
defer func() {
|
defer rt.leaveScope()
|
||||||
self.leaveScope()
|
|
||||||
}()
|
|
||||||
}
|
}
|
||||||
self.cmpl_functionDeclaration(node.functionList)
|
rt.cmplFunctionDeclaration(node.functionList)
|
||||||
self.cmpl_variableDeclaration(node.varList)
|
rt.cmplVariableDeclaration(node.varList)
|
||||||
self.scope.frame.file = node.file
|
rt.scope.frame.file = node.file
|
||||||
return self.cmpl_evaluate_nodeStatementList(node.body)
|
return rt.cmplEvaluateNodeStatementList(node.body)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_runtime) cmpl_call_nodeFunction(function *_object, stash *_fnStash, node *_nodeFunctionLiteral, this Value, argumentList []Value) Value {
|
func (rt *runtime) cmplCallNodeFunction(function *object, stash *fnStash, node *nodeFunctionLiteral, argumentList []Value) Value {
|
||||||
indexOfParameterName := make([]string, len(argumentList))
|
indexOfParameterName := make([]string, len(argumentList))
|
||||||
// function(abc, def, ghi)
|
// function(abc, def, ghi)
|
||||||
// indexOfParameterName[0] = "abc"
|
// indexOfParameterName[0] = "abc"
|
||||||
|
@ -36,28 +34,28 @@ func (self *_runtime) cmpl_call_nodeFunction(function *_object, stash *_fnStash,
|
||||||
indexOfParameterName[index] = name
|
indexOfParameterName[index] = name
|
||||||
}
|
}
|
||||||
// strict = false
|
// strict = false
|
||||||
self.scope.lexical.setValue(name, value, false)
|
rt.scope.lexical.setValue(name, value, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !argumentsFound {
|
if !argumentsFound {
|
||||||
arguments := self.newArgumentsObject(indexOfParameterName, stash, len(argumentList))
|
arguments := rt.newArgumentsObject(indexOfParameterName, stash, len(argumentList))
|
||||||
arguments.defineProperty("callee", toValue_object(function), 0101, false)
|
arguments.defineProperty("callee", objectValue(function), 0o101, false)
|
||||||
stash.arguments = arguments
|
stash.arguments = arguments
|
||||||
// strict = false
|
// strict = false
|
||||||
self.scope.lexical.setValue("arguments", toValue_object(arguments), false)
|
rt.scope.lexical.setValue("arguments", objectValue(arguments), false)
|
||||||
for index, _ := range argumentList {
|
for index := range argumentList {
|
||||||
if index < len(node.parameterList) {
|
if index < len(node.parameterList) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
indexAsString := strconv.FormatInt(int64(index), 10)
|
indexAsString := strconv.FormatInt(int64(index), 10)
|
||||||
arguments.defineProperty(indexAsString, argumentList[index], 0111, false)
|
arguments.defineProperty(indexAsString, argumentList[index], 0o111, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.cmpl_functionDeclaration(node.functionList)
|
rt.cmplFunctionDeclaration(node.functionList)
|
||||||
self.cmpl_variableDeclaration(node.varList)
|
rt.cmplVariableDeclaration(node.varList)
|
||||||
|
|
||||||
result := self.cmpl_evaluate_nodeStatement(node.body)
|
result := rt.cmplEvaluateNodeStatement(node.body)
|
||||||
if result.kind == valueResult {
|
if result.kind == valueResult {
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
@ -65,16 +63,16 @@ func (self *_runtime) cmpl_call_nodeFunction(function *_object, stash *_fnStash,
|
||||||
return Value{}
|
return Value{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_runtime) cmpl_functionDeclaration(list []*_nodeFunctionLiteral) {
|
func (rt *runtime) cmplFunctionDeclaration(list []*nodeFunctionLiteral) {
|
||||||
executionContext := self.scope
|
executionContext := rt.scope
|
||||||
eval := executionContext.eval
|
eval := executionContext.eval
|
||||||
stash := executionContext.variable
|
stash := executionContext.variable
|
||||||
|
|
||||||
for _, function := range list {
|
for _, function := range list {
|
||||||
name := function.name
|
name := function.name
|
||||||
value := self.cmpl_evaluate_nodeExpression(function)
|
value := rt.cmplEvaluateNodeExpression(function)
|
||||||
if !stash.hasBinding(name) {
|
if !stash.hasBinding(name) {
|
||||||
stash.createBinding(name, eval == true, value)
|
stash.createBinding(name, eval, value)
|
||||||
} else {
|
} else {
|
||||||
// TODO 10.5.5.e
|
// TODO 10.5.5.e
|
||||||
stash.setBinding(name, value, false) // TODO strict
|
stash.setBinding(name, value, false) // TODO strict
|
||||||
|
@ -82,14 +80,14 @@ func (self *_runtime) cmpl_functionDeclaration(list []*_nodeFunctionLiteral) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_runtime) cmpl_variableDeclaration(list []string) {
|
func (rt *runtime) cmplVariableDeclaration(list []string) {
|
||||||
executionContext := self.scope
|
executionContext := rt.scope
|
||||||
eval := executionContext.eval
|
eval := executionContext.eval
|
||||||
stash := executionContext.variable
|
stash := executionContext.variable
|
||||||
|
|
||||||
for _, name := range list {
|
for _, name := range list {
|
||||||
if !stash.hasBinding(name) {
|
if !stash.hasBinding(name) {
|
||||||
stash.createBinding(name, eval == true, Value{}) // TODO strict?
|
stash.createBinding(name, eval, Value{}) // TODO strict?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
359
v1/vendor/github.com/robertkrimen/otto/cmpl_evaluate_expression.go
generated
vendored
|
@ -3,136 +3,135 @@ package otto
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
"runtime"
|
goruntime "runtime"
|
||||||
|
|
||||||
"github.com/robertkrimen/otto/token"
|
"github.com/robertkrimen/otto/token"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (self *_runtime) cmpl_evaluate_nodeExpression(node _nodeExpression) Value {
|
func (rt *runtime) cmplEvaluateNodeExpression(node nodeExpression) Value {
|
||||||
// Allow interpreter interruption
|
// Allow interpreter interruption
|
||||||
// If the Interrupt channel is nil, then
|
// If the Interrupt channel is nil, then
|
||||||
// we avoid runtime.Gosched() overhead (if any)
|
// we avoid runtime.Gosched() overhead (if any)
|
||||||
// FIXME: Test this
|
// FIXME: Test this
|
||||||
if self.otto.Interrupt != nil {
|
if rt.otto.Interrupt != nil {
|
||||||
runtime.Gosched()
|
goruntime.Gosched()
|
||||||
select {
|
select {
|
||||||
case value := <-self.otto.Interrupt:
|
case value := <-rt.otto.Interrupt:
|
||||||
value()
|
value()
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch node := node.(type) {
|
switch node := node.(type) {
|
||||||
case *_nodeArrayLiteral:
|
case *nodeArrayLiteral:
|
||||||
return self.cmpl_evaluate_nodeArrayLiteral(node)
|
return rt.cmplEvaluateNodeArrayLiteral(node)
|
||||||
|
|
||||||
case *_nodeAssignExpression:
|
case *nodeAssignExpression:
|
||||||
return self.cmpl_evaluate_nodeAssignExpression(node)
|
return rt.cmplEvaluateNodeAssignExpression(node)
|
||||||
|
|
||||||
case *_nodeBinaryExpression:
|
case *nodeBinaryExpression:
|
||||||
if node.comparison {
|
if node.comparison {
|
||||||
return self.cmpl_evaluate_nodeBinaryExpression_comparison(node)
|
return rt.cmplEvaluateNodeBinaryExpressionComparison(node)
|
||||||
} else {
|
|
||||||
return self.cmpl_evaluate_nodeBinaryExpression(node)
|
|
||||||
}
|
}
|
||||||
|
return rt.cmplEvaluateNodeBinaryExpression(node)
|
||||||
|
|
||||||
case *_nodeBracketExpression:
|
case *nodeBracketExpression:
|
||||||
return self.cmpl_evaluate_nodeBracketExpression(node)
|
return rt.cmplEvaluateNodeBracketExpression(node)
|
||||||
|
|
||||||
case *_nodeCallExpression:
|
case *nodeCallExpression:
|
||||||
return self.cmpl_evaluate_nodeCallExpression(node, nil)
|
return rt.cmplEvaluateNodeCallExpression(node, nil)
|
||||||
|
|
||||||
case *_nodeConditionalExpression:
|
case *nodeConditionalExpression:
|
||||||
return self.cmpl_evaluate_nodeConditionalExpression(node)
|
return rt.cmplEvaluateNodeConditionalExpression(node)
|
||||||
|
|
||||||
case *_nodeDotExpression:
|
case *nodeDotExpression:
|
||||||
return self.cmpl_evaluate_nodeDotExpression(node)
|
return rt.cmplEvaluateNodeDotExpression(node)
|
||||||
|
|
||||||
case *_nodeFunctionLiteral:
|
case *nodeFunctionLiteral:
|
||||||
var local = self.scope.lexical
|
local := rt.scope.lexical
|
||||||
if node.name != "" {
|
if node.name != "" {
|
||||||
local = self.newDeclarationStash(local)
|
local = rt.newDeclarationStash(local)
|
||||||
}
|
}
|
||||||
|
|
||||||
value := toValue_object(self.newNodeFunction(node, local))
|
value := objectValue(rt.newNodeFunction(node, local))
|
||||||
if node.name != "" {
|
if node.name != "" {
|
||||||
local.createBinding(node.name, false, value)
|
local.createBinding(node.name, false, value)
|
||||||
}
|
}
|
||||||
return value
|
return value
|
||||||
|
|
||||||
case *_nodeIdentifier:
|
case *nodeIdentifier:
|
||||||
name := node.name
|
name := node.name
|
||||||
// TODO Should be true or false (strictness) depending on context
|
// TODO Should be true or false (strictness) depending on context
|
||||||
// getIdentifierReference should not return nil, but we check anyway and panic
|
// getIdentifierReference should not return nil, but we check anyway and panic
|
||||||
// so as not to propagate the nil into something else
|
// so as not to propagate the nil into something else
|
||||||
reference := getIdentifierReference(self, self.scope.lexical, name, false, _at(node.idx))
|
reference := getIdentifierReference(rt, rt.scope.lexical, name, false, at(node.idx))
|
||||||
if reference == nil {
|
if reference == nil {
|
||||||
// Should never get here!
|
// Should never get here!
|
||||||
panic(hereBeDragons("referenceError == nil: " + name))
|
panic(hereBeDragons("referenceError == nil: " + name))
|
||||||
}
|
}
|
||||||
return toValue(reference)
|
return toValue(reference)
|
||||||
|
|
||||||
case *_nodeLiteral:
|
case *nodeLiteral:
|
||||||
return node.value
|
return node.value
|
||||||
|
|
||||||
case *_nodeNewExpression:
|
case *nodeNewExpression:
|
||||||
return self.cmpl_evaluate_nodeNewExpression(node)
|
return rt.cmplEvaluateNodeNewExpression(node)
|
||||||
|
|
||||||
case *_nodeObjectLiteral:
|
case *nodeObjectLiteral:
|
||||||
return self.cmpl_evaluate_nodeObjectLiteral(node)
|
return rt.cmplEvaluateNodeObjectLiteral(node)
|
||||||
|
|
||||||
case *_nodeRegExpLiteral:
|
case *nodeRegExpLiteral:
|
||||||
return toValue_object(self._newRegExp(node.pattern, node.flags))
|
return objectValue(rt.newRegExpDirect(node.pattern, node.flags))
|
||||||
|
|
||||||
case *_nodeSequenceExpression:
|
case *nodeSequenceExpression:
|
||||||
return self.cmpl_evaluate_nodeSequenceExpression(node)
|
return rt.cmplEvaluateNodeSequenceExpression(node)
|
||||||
|
|
||||||
case *_nodeThisExpression:
|
case *nodeThisExpression:
|
||||||
return toValue_object(self.scope.this)
|
return objectValue(rt.scope.this)
|
||||||
|
|
||||||
case *_nodeUnaryExpression:
|
case *nodeUnaryExpression:
|
||||||
return self.cmpl_evaluate_nodeUnaryExpression(node)
|
return rt.cmplEvaluateNodeUnaryExpression(node)
|
||||||
|
|
||||||
case *_nodeVariableExpression:
|
case *nodeVariableExpression:
|
||||||
return self.cmpl_evaluate_nodeVariableExpression(node)
|
return rt.cmplEvaluateNodeVariableExpression(node)
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("unknown node type: %T", node))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
panic(fmt.Errorf("Here be dragons: evaluate_nodeExpression(%T)", node))
|
func (rt *runtime) cmplEvaluateNodeArrayLiteral(node *nodeArrayLiteral) Value {
|
||||||
}
|
|
||||||
|
|
||||||
func (self *_runtime) cmpl_evaluate_nodeArrayLiteral(node *_nodeArrayLiteral) Value {
|
|
||||||
valueArray := []Value{}
|
valueArray := []Value{}
|
||||||
|
|
||||||
for _, node := range node.value {
|
for _, node := range node.value {
|
||||||
if node == nil {
|
if node == nil {
|
||||||
valueArray = append(valueArray, emptyValue)
|
valueArray = append(valueArray, emptyValue)
|
||||||
} else {
|
} else {
|
||||||
valueArray = append(valueArray, self.cmpl_evaluate_nodeExpression(node).resolve())
|
valueArray = append(valueArray, rt.cmplEvaluateNodeExpression(node).resolve())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
result := self.newArrayOf(valueArray)
|
result := rt.newArrayOf(valueArray)
|
||||||
|
|
||||||
return toValue_object(result)
|
return objectValue(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_runtime) cmpl_evaluate_nodeAssignExpression(node *_nodeAssignExpression) Value {
|
func (rt *runtime) cmplEvaluateNodeAssignExpression(node *nodeAssignExpression) Value {
|
||||||
left := self.cmpl_evaluate_nodeExpression(node.left)
|
left := rt.cmplEvaluateNodeExpression(node.left)
|
||||||
right := self.cmpl_evaluate_nodeExpression(node.right)
|
right := rt.cmplEvaluateNodeExpression(node.right)
|
||||||
rightValue := right.resolve()
|
rightValue := right.resolve()
|
||||||
|
|
||||||
result := rightValue
|
result := rightValue
|
||||||
if node.operator != token.ASSIGN {
|
if node.operator != token.ASSIGN {
|
||||||
result = self.calculateBinaryExpression(node.operator, left, rightValue)
|
result = rt.calculateBinaryExpression(node.operator, left, rightValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
self.putValue(left.reference(), result)
|
rt.putValue(left.reference(), result)
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_runtime) cmpl_evaluate_nodeBinaryExpression(node *_nodeBinaryExpression) Value {
|
func (rt *runtime) cmplEvaluateNodeBinaryExpression(node *nodeBinaryExpression) Value {
|
||||||
left := self.cmpl_evaluate_nodeExpression(node.left)
|
left := rt.cmplEvaluateNodeExpression(node.left)
|
||||||
leftValue := left.resolve()
|
leftValue := left.resolve()
|
||||||
|
|
||||||
switch node.operator {
|
switch node.operator {
|
||||||
|
@ -141,214 +140,206 @@ func (self *_runtime) cmpl_evaluate_nodeBinaryExpression(node *_nodeBinaryExpres
|
||||||
if !leftValue.bool() {
|
if !leftValue.bool() {
|
||||||
return leftValue
|
return leftValue
|
||||||
}
|
}
|
||||||
right := self.cmpl_evaluate_nodeExpression(node.right)
|
right := rt.cmplEvaluateNodeExpression(node.right)
|
||||||
return right.resolve()
|
return right.resolve()
|
||||||
case token.LOGICAL_OR:
|
case token.LOGICAL_OR:
|
||||||
if leftValue.bool() {
|
if leftValue.bool() {
|
||||||
return leftValue
|
return leftValue
|
||||||
}
|
}
|
||||||
right := self.cmpl_evaluate_nodeExpression(node.right)
|
right := rt.cmplEvaluateNodeExpression(node.right)
|
||||||
return right.resolve()
|
return right.resolve()
|
||||||
}
|
}
|
||||||
|
|
||||||
return self.calculateBinaryExpression(node.operator, leftValue, self.cmpl_evaluate_nodeExpression(node.right))
|
return rt.calculateBinaryExpression(node.operator, leftValue, rt.cmplEvaluateNodeExpression(node.right))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_runtime) cmpl_evaluate_nodeBinaryExpression_comparison(node *_nodeBinaryExpression) Value {
|
func (rt *runtime) cmplEvaluateNodeBinaryExpressionComparison(node *nodeBinaryExpression) Value {
|
||||||
left := self.cmpl_evaluate_nodeExpression(node.left).resolve()
|
left := rt.cmplEvaluateNodeExpression(node.left).resolve()
|
||||||
right := self.cmpl_evaluate_nodeExpression(node.right).resolve()
|
right := rt.cmplEvaluateNodeExpression(node.right).resolve()
|
||||||
|
|
||||||
return toValue_bool(self.calculateComparison(node.operator, left, right))
|
return boolValue(rt.calculateComparison(node.operator, left, right))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_runtime) cmpl_evaluate_nodeBracketExpression(node *_nodeBracketExpression) Value {
|
func (rt *runtime) cmplEvaluateNodeBracketExpression(node *nodeBracketExpression) Value {
|
||||||
target := self.cmpl_evaluate_nodeExpression(node.left)
|
target := rt.cmplEvaluateNodeExpression(node.left)
|
||||||
targetValue := target.resolve()
|
targetValue := target.resolve()
|
||||||
member := self.cmpl_evaluate_nodeExpression(node.member)
|
member := rt.cmplEvaluateNodeExpression(node.member)
|
||||||
memberValue := member.resolve()
|
memberValue := member.resolve()
|
||||||
|
|
||||||
// TODO Pass in base value as-is, and defer toObject till later?
|
// TODO Pass in base value as-is, and defer toObject till later?
|
||||||
object, err := self.objectCoerce(targetValue)
|
obj, err := rt.objectCoerce(targetValue)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(self.panicTypeError("Cannot access member '%s' of %s", memberValue.string(), err.Error(), _at(node.idx)))
|
panic(rt.panicTypeError("Cannot access member %q of %s", memberValue.string(), err, at(node.idx)))
|
||||||
}
|
}
|
||||||
return toValue(newPropertyReference(self, object, memberValue.string(), false, _at(node.idx)))
|
return toValue(newPropertyReference(rt, obj, memberValue.string(), false, at(node.idx)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_runtime) cmpl_evaluate_nodeCallExpression(node *_nodeCallExpression, withArgumentList []interface{}) Value {
|
func (rt *runtime) cmplEvaluateNodeCallExpression(node *nodeCallExpression, withArgumentList []interface{}) Value {
|
||||||
rt := self
|
|
||||||
this := Value{}
|
this := Value{}
|
||||||
callee := self.cmpl_evaluate_nodeExpression(node.callee)
|
callee := rt.cmplEvaluateNodeExpression(node.callee)
|
||||||
|
|
||||||
argumentList := []Value{}
|
argumentList := []Value{}
|
||||||
if withArgumentList != nil {
|
if withArgumentList != nil {
|
||||||
argumentList = self.toValueArray(withArgumentList...)
|
argumentList = rt.toValueArray(withArgumentList...)
|
||||||
} else {
|
} else {
|
||||||
for _, argumentNode := range node.argumentList {
|
for _, argumentNode := range node.argumentList {
|
||||||
argumentList = append(argumentList, self.cmpl_evaluate_nodeExpression(argumentNode).resolve())
|
argumentList = append(argumentList, rt.cmplEvaluateNodeExpression(argumentNode).resolve())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rf := callee.reference()
|
|
||||||
vl := callee.resolve()
|
|
||||||
|
|
||||||
eval := false // Whether this call is a (candidate for) direct call to eval
|
eval := false // Whether this call is a (candidate for) direct call to eval
|
||||||
name := ""
|
name := ""
|
||||||
if rf != nil {
|
if rf := callee.reference(); rf != nil {
|
||||||
switch rf := rf.(type) {
|
switch rf := rf.(type) {
|
||||||
case *_propertyReference:
|
case *propertyReference:
|
||||||
name = rf.name
|
name = rf.name
|
||||||
object := rf.base
|
this = objectValue(rf.base)
|
||||||
this = toValue_object(object)
|
|
||||||
eval = rf.name == "eval" // Possible direct eval
|
eval = rf.name == "eval" // Possible direct eval
|
||||||
case *_stashReference:
|
case *stashReference:
|
||||||
// TODO ImplicitThisValue
|
// TODO ImplicitThisValue
|
||||||
name = rf.name
|
name = rf.name
|
||||||
eval = rf.name == "eval" // Possible direct eval
|
eval = rf.name == "eval" // Possible direct eval
|
||||||
default:
|
default:
|
||||||
// FIXME?
|
// FIXME?
|
||||||
panic(rt.panicTypeError("Here be dragons"))
|
panic(rt.panicTypeError("unexpected callee type %T to node call expression", rf))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
at := _at(-1)
|
atv := at(-1)
|
||||||
switch callee := node.callee.(type) {
|
switch callee := node.callee.(type) {
|
||||||
case *_nodeIdentifier:
|
case *nodeIdentifier:
|
||||||
at = _at(callee.idx)
|
atv = at(callee.idx)
|
||||||
case *_nodeDotExpression:
|
case *nodeDotExpression:
|
||||||
at = _at(callee.idx)
|
atv = at(callee.idx)
|
||||||
case *_nodeBracketExpression:
|
case *nodeBracketExpression:
|
||||||
at = _at(callee.idx)
|
atv = at(callee.idx)
|
||||||
}
|
}
|
||||||
|
|
||||||
frame := _frame{
|
frm := frame{
|
||||||
callee: name,
|
callee: name,
|
||||||
file: self.scope.frame.file,
|
file: rt.scope.frame.file,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vl := callee.resolve()
|
||||||
if !vl.IsFunction() {
|
if !vl.IsFunction() {
|
||||||
if name == "" {
|
if name == "" {
|
||||||
// FIXME Maybe typeof?
|
// FIXME Maybe typeof?
|
||||||
panic(rt.panicTypeError("%v is not a function", vl, at))
|
panic(rt.panicTypeError("%v is not a function", vl, atv))
|
||||||
}
|
}
|
||||||
panic(rt.panicTypeError("'%s' is not a function", name, at))
|
panic(rt.panicTypeError("%q is not a function", name, atv))
|
||||||
}
|
}
|
||||||
|
|
||||||
self.scope.frame.offset = int(at)
|
rt.scope.frame.offset = int(atv)
|
||||||
|
|
||||||
return vl._object().call(this, argumentList, eval, frame)
|
return vl.object().call(this, argumentList, eval, frm)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_runtime) cmpl_evaluate_nodeConditionalExpression(node *_nodeConditionalExpression) Value {
|
func (rt *runtime) cmplEvaluateNodeConditionalExpression(node *nodeConditionalExpression) Value {
|
||||||
test := self.cmpl_evaluate_nodeExpression(node.test)
|
test := rt.cmplEvaluateNodeExpression(node.test)
|
||||||
testValue := test.resolve()
|
testValue := test.resolve()
|
||||||
if testValue.bool() {
|
if testValue.bool() {
|
||||||
return self.cmpl_evaluate_nodeExpression(node.consequent)
|
return rt.cmplEvaluateNodeExpression(node.consequent)
|
||||||
}
|
}
|
||||||
return self.cmpl_evaluate_nodeExpression(node.alternate)
|
return rt.cmplEvaluateNodeExpression(node.alternate)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_runtime) cmpl_evaluate_nodeDotExpression(node *_nodeDotExpression) Value {
|
func (rt *runtime) cmplEvaluateNodeDotExpression(node *nodeDotExpression) Value {
|
||||||
target := self.cmpl_evaluate_nodeExpression(node.left)
|
target := rt.cmplEvaluateNodeExpression(node.left)
|
||||||
targetValue := target.resolve()
|
targetValue := target.resolve()
|
||||||
// TODO Pass in base value as-is, and defer toObject till later?
|
// TODO Pass in base value as-is, and defer toObject till later?
|
||||||
object, err := self.objectCoerce(targetValue)
|
obj, err := rt.objectCoerce(targetValue)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(self.panicTypeError("Cannot access member '%s' of %s", node.identifier, err.Error(), _at(node.idx)))
|
panic(rt.panicTypeError("Cannot access member %q of %s", node.identifier, err, at(node.idx)))
|
||||||
}
|
}
|
||||||
return toValue(newPropertyReference(self, object, node.identifier, false, _at(node.idx)))
|
return toValue(newPropertyReference(rt, obj, node.identifier, false, at(node.idx)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_runtime) cmpl_evaluate_nodeNewExpression(node *_nodeNewExpression) Value {
|
func (rt *runtime) cmplEvaluateNodeNewExpression(node *nodeNewExpression) Value {
|
||||||
rt := self
|
callee := rt.cmplEvaluateNodeExpression(node.callee)
|
||||||
callee := self.cmpl_evaluate_nodeExpression(node.callee)
|
|
||||||
|
|
||||||
argumentList := []Value{}
|
argumentList := []Value{}
|
||||||
for _, argumentNode := range node.argumentList {
|
for _, argumentNode := range node.argumentList {
|
||||||
argumentList = append(argumentList, self.cmpl_evaluate_nodeExpression(argumentNode).resolve())
|
argumentList = append(argumentList, rt.cmplEvaluateNodeExpression(argumentNode).resolve())
|
||||||
}
|
}
|
||||||
|
|
||||||
rf := callee.reference()
|
var name string
|
||||||
vl := callee.resolve()
|
if rf := callee.reference(); rf != nil {
|
||||||
|
|
||||||
name := ""
|
|
||||||
if rf != nil {
|
|
||||||
switch rf := rf.(type) {
|
switch rf := rf.(type) {
|
||||||
case *_propertyReference:
|
case *propertyReference:
|
||||||
name = rf.name
|
name = rf.name
|
||||||
case *_stashReference:
|
case *stashReference:
|
||||||
name = rf.name
|
name = rf.name
|
||||||
default:
|
default:
|
||||||
panic(rt.panicTypeError("Here be dragons"))
|
panic(rt.panicTypeError("node new expression unexpected callee type %T", rf))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
at := _at(-1)
|
atv := at(-1)
|
||||||
switch callee := node.callee.(type) {
|
switch callee := node.callee.(type) {
|
||||||
case *_nodeIdentifier:
|
case *nodeIdentifier:
|
||||||
at = _at(callee.idx)
|
atv = at(callee.idx)
|
||||||
case *_nodeDotExpression:
|
case *nodeDotExpression:
|
||||||
at = _at(callee.idx)
|
atv = at(callee.idx)
|
||||||
case *_nodeBracketExpression:
|
case *nodeBracketExpression:
|
||||||
at = _at(callee.idx)
|
atv = at(callee.idx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vl := callee.resolve()
|
||||||
if !vl.IsFunction() {
|
if !vl.IsFunction() {
|
||||||
if name == "" {
|
if name == "" {
|
||||||
// FIXME Maybe typeof?
|
// FIXME Maybe typeof?
|
||||||
panic(rt.panicTypeError("%v is not a function", vl, at))
|
panic(rt.panicTypeError("%v is not a function", vl, atv))
|
||||||
}
|
}
|
||||||
panic(rt.panicTypeError("'%s' is not a function", name, at))
|
panic(rt.panicTypeError("'%s' is not a function", name, atv))
|
||||||
}
|
}
|
||||||
|
|
||||||
self.scope.frame.offset = int(at)
|
rt.scope.frame.offset = int(atv)
|
||||||
|
|
||||||
return vl._object().construct(argumentList)
|
return vl.object().construct(argumentList)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_runtime) cmpl_evaluate_nodeObjectLiteral(node *_nodeObjectLiteral) Value {
|
func (rt *runtime) cmplEvaluateNodeObjectLiteral(node *nodeObjectLiteral) Value {
|
||||||
result := self.newObject()
|
result := rt.newObject()
|
||||||
|
for _, prop := range node.value {
|
||||||
for _, property := range node.value {
|
switch prop.kind {
|
||||||
switch property.kind {
|
|
||||||
case "value":
|
case "value":
|
||||||
result.defineProperty(property.key, self.cmpl_evaluate_nodeExpression(property.value).resolve(), 0111, false)
|
result.defineProperty(prop.key, rt.cmplEvaluateNodeExpression(prop.value).resolve(), 0o111, false)
|
||||||
case "get":
|
case "get":
|
||||||
getter := self.newNodeFunction(property.value.(*_nodeFunctionLiteral), self.scope.lexical)
|
getter := rt.newNodeFunction(prop.value.(*nodeFunctionLiteral), rt.scope.lexical)
|
||||||
descriptor := _property{}
|
descriptor := property{}
|
||||||
descriptor.mode = 0211
|
descriptor.mode = 0o211
|
||||||
descriptor.value = _propertyGetSet{getter, nil}
|
descriptor.value = propertyGetSet{getter, nil}
|
||||||
result.defineOwnProperty(property.key, descriptor, false)
|
result.defineOwnProperty(prop.key, descriptor, false)
|
||||||
case "set":
|
case "set":
|
||||||
setter := self.newNodeFunction(property.value.(*_nodeFunctionLiteral), self.scope.lexical)
|
setter := rt.newNodeFunction(prop.value.(*nodeFunctionLiteral), rt.scope.lexical)
|
||||||
descriptor := _property{}
|
descriptor := property{}
|
||||||
descriptor.mode = 0211
|
descriptor.mode = 0o211
|
||||||
descriptor.value = _propertyGetSet{nil, setter}
|
descriptor.value = propertyGetSet{nil, setter}
|
||||||
result.defineOwnProperty(property.key, descriptor, false)
|
result.defineOwnProperty(prop.key, descriptor, false)
|
||||||
default:
|
default:
|
||||||
panic(fmt.Errorf("Here be dragons: evaluate_nodeObjectLiteral: invalid property.Kind: %v", property.kind))
|
panic(fmt.Sprintf("unknown node object literal property kind %T", prop.kind))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return toValue_object(result)
|
return objectValue(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_runtime) cmpl_evaluate_nodeSequenceExpression(node *_nodeSequenceExpression) Value {
|
func (rt *runtime) cmplEvaluateNodeSequenceExpression(node *nodeSequenceExpression) Value {
|
||||||
var result Value
|
var result Value
|
||||||
for _, node := range node.sequence {
|
for _, node := range node.sequence {
|
||||||
result = self.cmpl_evaluate_nodeExpression(node)
|
result = rt.cmplEvaluateNodeExpression(node)
|
||||||
result = result.resolve()
|
result = result.resolve()
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_runtime) cmpl_evaluate_nodeUnaryExpression(node *_nodeUnaryExpression) Value {
|
func (rt *runtime) cmplEvaluateNodeUnaryExpression(node *nodeUnaryExpression) Value {
|
||||||
target := self.cmpl_evaluate_nodeExpression(node.operand)
|
target := rt.cmplEvaluateNodeExpression(node.operand)
|
||||||
switch node.operator {
|
switch node.operator {
|
||||||
case token.TYPEOF, token.DELETE:
|
case token.TYPEOF, token.DELETE:
|
||||||
if target.kind == valueReference && target.reference().invalid() {
|
if target.kind == valueReference && target.reference().invalid() {
|
||||||
if node.operator == token.TYPEOF {
|
if node.operator == token.TYPEOF {
|
||||||
return toValue_string("undefined")
|
return stringValue("undefined")
|
||||||
}
|
}
|
||||||
return trueValue
|
return trueValue
|
||||||
}
|
}
|
||||||
|
@ -364,10 +355,10 @@ func (self *_runtime) cmpl_evaluate_nodeUnaryExpression(node *_nodeUnaryExpressi
|
||||||
case token.BITWISE_NOT:
|
case token.BITWISE_NOT:
|
||||||
targetValue := target.resolve()
|
targetValue := target.resolve()
|
||||||
integerValue := toInt32(targetValue)
|
integerValue := toInt32(targetValue)
|
||||||
return toValue_int32(^integerValue)
|
return int32Value(^integerValue)
|
||||||
case token.PLUS:
|
case token.PLUS:
|
||||||
targetValue := target.resolve()
|
targetValue := target.resolve()
|
||||||
return toValue_float64(targetValue.float64())
|
return float64Value(targetValue.float64())
|
||||||
case token.MINUS:
|
case token.MINUS:
|
||||||
targetValue := target.resolve()
|
targetValue := target.resolve()
|
||||||
value := targetValue.float64()
|
value := targetValue.float64()
|
||||||
|
@ -376,35 +367,35 @@ func (self *_runtime) cmpl_evaluate_nodeUnaryExpression(node *_nodeUnaryExpressi
|
||||||
if math.Signbit(value) {
|
if math.Signbit(value) {
|
||||||
sign = 1
|
sign = 1
|
||||||
}
|
}
|
||||||
return toValue_float64(math.Copysign(value, sign))
|
return float64Value(math.Copysign(value, sign))
|
||||||
case token.INCREMENT:
|
case token.INCREMENT:
|
||||||
targetValue := target.resolve()
|
targetValue := target.resolve()
|
||||||
if node.postfix {
|
if node.postfix {
|
||||||
// Postfix++
|
// Postfix++
|
||||||
oldValue := targetValue.float64()
|
oldValue := targetValue.float64()
|
||||||
newValue := toValue_float64(+1 + oldValue)
|
newValue := float64Value(+1 + oldValue)
|
||||||
self.putValue(target.reference(), newValue)
|
rt.putValue(target.reference(), newValue)
|
||||||
return toValue_float64(oldValue)
|
return float64Value(oldValue)
|
||||||
} else {
|
|
||||||
// ++Prefix
|
|
||||||
newValue := toValue_float64(+1 + targetValue.float64())
|
|
||||||
self.putValue(target.reference(), newValue)
|
|
||||||
return newValue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ++Prefix
|
||||||
|
newValue := float64Value(+1 + targetValue.float64())
|
||||||
|
rt.putValue(target.reference(), newValue)
|
||||||
|
return newValue
|
||||||
case token.DECREMENT:
|
case token.DECREMENT:
|
||||||
targetValue := target.resolve()
|
targetValue := target.resolve()
|
||||||
if node.postfix {
|
if node.postfix {
|
||||||
// Postfix--
|
// Postfix--
|
||||||
oldValue := targetValue.float64()
|
oldValue := targetValue.float64()
|
||||||
newValue := toValue_float64(-1 + oldValue)
|
newValue := float64Value(-1 + oldValue)
|
||||||
self.putValue(target.reference(), newValue)
|
rt.putValue(target.reference(), newValue)
|
||||||
return toValue_float64(oldValue)
|
return float64Value(oldValue)
|
||||||
} else {
|
|
||||||
// --Prefix
|
|
||||||
newValue := toValue_float64(-1 + targetValue.float64())
|
|
||||||
self.putValue(target.reference(), newValue)
|
|
||||||
return newValue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --Prefix
|
||||||
|
newValue := float64Value(-1 + targetValue.float64())
|
||||||
|
rt.putValue(target.reference(), newValue)
|
||||||
|
return newValue
|
||||||
case token.VOID:
|
case token.VOID:
|
||||||
target.resolve() // FIXME Side effect?
|
target.resolve() // FIXME Side effect?
|
||||||
return Value{}
|
return Value{}
|
||||||
|
@ -413,25 +404,25 @@ func (self *_runtime) cmpl_evaluate_nodeUnaryExpression(node *_nodeUnaryExpressi
|
||||||
if reference == nil {
|
if reference == nil {
|
||||||
return trueValue
|
return trueValue
|
||||||
}
|
}
|
||||||
return toValue_bool(target.reference().delete())
|
return boolValue(target.reference().delete())
|
||||||
case token.TYPEOF:
|
case token.TYPEOF:
|
||||||
targetValue := target.resolve()
|
targetValue := target.resolve()
|
||||||
switch targetValue.kind {
|
switch targetValue.kind {
|
||||||
case valueUndefined:
|
case valueUndefined:
|
||||||
return toValue_string("undefined")
|
return stringValue("undefined")
|
||||||
case valueNull:
|
case valueNull:
|
||||||
return toValue_string("object")
|
return stringValue("object")
|
||||||
case valueBoolean:
|
case valueBoolean:
|
||||||
return toValue_string("boolean")
|
return stringValue("boolean")
|
||||||
case valueNumber:
|
case valueNumber:
|
||||||
return toValue_string("number")
|
return stringValue("number")
|
||||||
case valueString:
|
case valueString:
|
||||||
return toValue_string("string")
|
return stringValue("string")
|
||||||
case valueObject:
|
case valueObject:
|
||||||
if targetValue._object().isCall() {
|
if targetValue.object().isCall() {
|
||||||
return toValue_string("function")
|
return stringValue("function")
|
||||||
}
|
}
|
||||||
return toValue_string("object")
|
return stringValue("object")
|
||||||
default:
|
default:
|
||||||
// FIXME ?
|
// FIXME ?
|
||||||
}
|
}
|
||||||
|
@ -440,14 +431,14 @@ func (self *_runtime) cmpl_evaluate_nodeUnaryExpression(node *_nodeUnaryExpressi
|
||||||
panic(hereBeDragons())
|
panic(hereBeDragons())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_runtime) cmpl_evaluate_nodeVariableExpression(node *_nodeVariableExpression) Value {
|
func (rt *runtime) cmplEvaluateNodeVariableExpression(node *nodeVariableExpression) Value {
|
||||||
if node.initializer != nil {
|
if node.initializer != nil {
|
||||||
// FIXME If reference is nil
|
// FIXME If reference is nil
|
||||||
left := getIdentifierReference(self, self.scope.lexical, node.name, false, _at(node.idx))
|
left := getIdentifierReference(rt, rt.scope.lexical, node.name, false, at(node.idx))
|
||||||
right := self.cmpl_evaluate_nodeExpression(node.initializer)
|
right := rt.cmplEvaluateNodeExpression(node.initializer)
|
||||||
rightValue := right.resolve()
|
rightValue := right.resolve()
|
||||||
|
|
||||||
self.putValue(left, rightValue)
|
rt.putValue(left, rightValue)
|
||||||
}
|
}
|
||||||
return toValue_string(node.name)
|
return stringValue(node.name)
|
||||||
}
|
}
|
||||||
|
|
238
v1/vendor/github.com/robertkrimen/otto/cmpl_evaluate_statement.go
generated
vendored
|
@ -2,121 +2,121 @@ package otto
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"runtime"
|
goruntime "runtime"
|
||||||
|
|
||||||
"github.com/robertkrimen/otto/token"
|
"github.com/robertkrimen/otto/token"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (self *_runtime) cmpl_evaluate_nodeStatement(node _nodeStatement) Value {
|
func (rt *runtime) cmplEvaluateNodeStatement(node nodeStatement) Value {
|
||||||
// Allow interpreter interruption
|
// Allow interpreter interruption
|
||||||
// If the Interrupt channel is nil, then
|
// If the Interrupt channel is nil, then
|
||||||
// we avoid runtime.Gosched() overhead (if any)
|
// we avoid runtime.Gosched() overhead (if any)
|
||||||
// FIXME: Test this
|
// FIXME: Test this
|
||||||
if self.otto.Interrupt != nil {
|
if rt.otto.Interrupt != nil {
|
||||||
runtime.Gosched()
|
goruntime.Gosched()
|
||||||
select {
|
select {
|
||||||
case value := <-self.otto.Interrupt:
|
case value := <-rt.otto.Interrupt:
|
||||||
value()
|
value()
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch node := node.(type) {
|
switch node := node.(type) {
|
||||||
case *_nodeBlockStatement:
|
case *nodeBlockStatement:
|
||||||
labels := self.labels
|
labels := rt.labels
|
||||||
self.labels = nil
|
rt.labels = nil
|
||||||
|
|
||||||
value := self.cmpl_evaluate_nodeStatementList(node.list)
|
value := rt.cmplEvaluateNodeStatementList(node.list)
|
||||||
switch value.kind {
|
if value.kind == valueResult {
|
||||||
case valueResult:
|
if value.evaluateBreak(labels) == resultBreak {
|
||||||
switch value.evaluateBreak(labels) {
|
|
||||||
case resultBreak:
|
|
||||||
return emptyValue
|
return emptyValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return value
|
return value
|
||||||
|
|
||||||
case *_nodeBranchStatement:
|
case *nodeBranchStatement:
|
||||||
target := node.label
|
target := node.label
|
||||||
switch node.branch { // FIXME Maybe node.kind? node.operator?
|
switch node.branch { // FIXME Maybe node.kind? node.operator?
|
||||||
case token.BREAK:
|
case token.BREAK:
|
||||||
return toValue(newBreakResult(target))
|
return toValue(newBreakResult(target))
|
||||||
case token.CONTINUE:
|
case token.CONTINUE:
|
||||||
return toValue(newContinueResult(target))
|
return toValue(newContinueResult(target))
|
||||||
|
default:
|
||||||
|
panic(fmt.Errorf("unknown node branch token %T", node))
|
||||||
}
|
}
|
||||||
|
|
||||||
case *_nodeDebuggerStatement:
|
case *nodeDebuggerStatement:
|
||||||
if self.debugger != nil {
|
if rt.debugger != nil {
|
||||||
self.debugger(self.otto)
|
rt.debugger(rt.otto)
|
||||||
}
|
}
|
||||||
return emptyValue // Nothing happens.
|
return emptyValue // Nothing happens.
|
||||||
|
|
||||||
case *_nodeDoWhileStatement:
|
case *nodeDoWhileStatement:
|
||||||
return self.cmpl_evaluate_nodeDoWhileStatement(node)
|
return rt.cmplEvaluateNodeDoWhileStatement(node)
|
||||||
|
|
||||||
case *_nodeEmptyStatement:
|
case *nodeEmptyStatement:
|
||||||
return emptyValue
|
return emptyValue
|
||||||
|
|
||||||
case *_nodeExpressionStatement:
|
case *nodeExpressionStatement:
|
||||||
return self.cmpl_evaluate_nodeExpression(node.expression)
|
return rt.cmplEvaluateNodeExpression(node.expression)
|
||||||
|
|
||||||
case *_nodeForInStatement:
|
case *nodeForInStatement:
|
||||||
return self.cmpl_evaluate_nodeForInStatement(node)
|
return rt.cmplEvaluateNodeForInStatement(node)
|
||||||
|
|
||||||
case *_nodeForStatement:
|
case *nodeForStatement:
|
||||||
return self.cmpl_evaluate_nodeForStatement(node)
|
return rt.cmplEvaluateNodeForStatement(node)
|
||||||
|
|
||||||
case *_nodeIfStatement:
|
case *nodeIfStatement:
|
||||||
return self.cmpl_evaluate_nodeIfStatement(node)
|
return rt.cmplEvaluateNodeIfStatement(node)
|
||||||
|
|
||||||
case *_nodeLabelledStatement:
|
case *nodeLabelledStatement:
|
||||||
self.labels = append(self.labels, node.label)
|
rt.labels = append(rt.labels, node.label)
|
||||||
defer func() {
|
defer func() {
|
||||||
if len(self.labels) > 0 {
|
if len(rt.labels) > 0 {
|
||||||
self.labels = self.labels[:len(self.labels)-1] // Pop the label
|
rt.labels = rt.labels[:len(rt.labels)-1] // Pop the label
|
||||||
} else {
|
} else {
|
||||||
self.labels = nil
|
rt.labels = nil
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
return self.cmpl_evaluate_nodeStatement(node.statement)
|
return rt.cmplEvaluateNodeStatement(node.statement)
|
||||||
|
|
||||||
case *_nodeReturnStatement:
|
case *nodeReturnStatement:
|
||||||
if node.argument != nil {
|
if node.argument != nil {
|
||||||
return toValue(newReturnResult(self.cmpl_evaluate_nodeExpression(node.argument).resolve()))
|
return toValue(newReturnResult(rt.cmplEvaluateNodeExpression(node.argument).resolve()))
|
||||||
}
|
}
|
||||||
return toValue(newReturnResult(Value{}))
|
return toValue(newReturnResult(Value{}))
|
||||||
|
|
||||||
case *_nodeSwitchStatement:
|
case *nodeSwitchStatement:
|
||||||
return self.cmpl_evaluate_nodeSwitchStatement(node)
|
return rt.cmplEvaluateNodeSwitchStatement(node)
|
||||||
|
|
||||||
case *_nodeThrowStatement:
|
case *nodeThrowStatement:
|
||||||
value := self.cmpl_evaluate_nodeExpression(node.argument).resolve()
|
value := rt.cmplEvaluateNodeExpression(node.argument).resolve()
|
||||||
panic(newException(value))
|
panic(newException(value))
|
||||||
|
|
||||||
case *_nodeTryStatement:
|
case *nodeTryStatement:
|
||||||
return self.cmpl_evaluate_nodeTryStatement(node)
|
return rt.cmplEvaluateNodeTryStatement(node)
|
||||||
|
|
||||||
case *_nodeVariableStatement:
|
case *nodeVariableStatement:
|
||||||
// Variables are already defined, this is initialization only
|
// Variables are already defined, this is initialization only
|
||||||
for _, variable := range node.list {
|
for _, variable := range node.list {
|
||||||
self.cmpl_evaluate_nodeVariableExpression(variable.(*_nodeVariableExpression))
|
rt.cmplEvaluateNodeVariableExpression(variable.(*nodeVariableExpression))
|
||||||
}
|
}
|
||||||
return emptyValue
|
return emptyValue
|
||||||
|
|
||||||
case *_nodeWhileStatement:
|
case *nodeWhileStatement:
|
||||||
return self.cmpl_evaluate_nodeWhileStatement(node)
|
return rt.cmplEvaluateModeWhileStatement(node)
|
||||||
|
|
||||||
case *_nodeWithStatement:
|
case *nodeWithStatement:
|
||||||
return self.cmpl_evaluate_nodeWithStatement(node)
|
return rt.cmplEvaluateNodeWithStatement(node)
|
||||||
|
default:
|
||||||
|
panic(fmt.Errorf("unknown node statement type %T", node))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
panic(fmt.Errorf("Here be dragons: evaluate_nodeStatement(%T)", node))
|
func (rt *runtime) cmplEvaluateNodeStatementList(list []nodeStatement) Value {
|
||||||
}
|
|
||||||
|
|
||||||
func (self *_runtime) cmpl_evaluate_nodeStatementList(list []_nodeStatement) Value {
|
|
||||||
var result Value
|
var result Value
|
||||||
for _, node := range list {
|
for _, node := range list {
|
||||||
value := self.cmpl_evaluate_nodeStatement(node)
|
value := rt.cmplEvaluateNodeStatement(node)
|
||||||
switch value.kind {
|
switch value.kind {
|
||||||
case valueResult:
|
case valueResult:
|
||||||
return value
|
return value
|
||||||
|
@ -133,9 +133,9 @@ func (self *_runtime) cmpl_evaluate_nodeStatementList(list []_nodeStatement) Val
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_runtime) cmpl_evaluate_nodeDoWhileStatement(node *_nodeDoWhileStatement) Value {
|
func (rt *runtime) cmplEvaluateNodeDoWhileStatement(node *nodeDoWhileStatement) Value {
|
||||||
labels := append(self.labels, "")
|
labels := append(rt.labels, "") //nolint: gocritic
|
||||||
self.labels = nil
|
rt.labels = nil
|
||||||
|
|
||||||
test := node.test
|
test := node.test
|
||||||
|
|
||||||
|
@ -143,7 +143,7 @@ func (self *_runtime) cmpl_evaluate_nodeDoWhileStatement(node *_nodeDoWhileState
|
||||||
resultBreak:
|
resultBreak:
|
||||||
for {
|
for {
|
||||||
for _, node := range node.body {
|
for _, node := range node.body {
|
||||||
value := self.cmpl_evaluate_nodeStatement(node)
|
value := rt.cmplEvaluateNodeStatement(node)
|
||||||
switch value.kind {
|
switch value.kind {
|
||||||
case valueResult:
|
case valueResult:
|
||||||
switch value.evaluateBreakContinue(labels) {
|
switch value.evaluateBreakContinue(labels) {
|
||||||
|
@ -160,7 +160,7 @@ resultBreak:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
resultContinue:
|
resultContinue:
|
||||||
if !self.cmpl_evaluate_nodeExpression(test).resolve().bool() {
|
if !rt.cmplEvaluateNodeExpression(test).resolve().bool() {
|
||||||
// Stahp: do ... while (false)
|
// Stahp: do ... while (false)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -168,11 +168,11 @@ resultBreak:
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_runtime) cmpl_evaluate_nodeForInStatement(node *_nodeForInStatement) Value {
|
func (rt *runtime) cmplEvaluateNodeForInStatement(node *nodeForInStatement) Value {
|
||||||
labels := append(self.labels, "")
|
labels := append(rt.labels, "") //nolint: gocritic
|
||||||
self.labels = nil
|
rt.labels = nil
|
||||||
|
|
||||||
source := self.cmpl_evaluate_nodeExpression(node.source)
|
source := rt.cmplEvaluateNodeExpression(node.source)
|
||||||
sourceValue := source.resolve()
|
sourceValue := source.resolve()
|
||||||
|
|
||||||
switch sourceValue.kind {
|
switch sourceValue.kind {
|
||||||
|
@ -180,26 +180,26 @@ func (self *_runtime) cmpl_evaluate_nodeForInStatement(node *_nodeForInStatement
|
||||||
return emptyValue
|
return emptyValue
|
||||||
}
|
}
|
||||||
|
|
||||||
sourceObject := self.toObject(sourceValue)
|
sourceObject := rt.toObject(sourceValue)
|
||||||
|
|
||||||
into := node.into
|
into := node.into
|
||||||
body := node.body
|
body := node.body
|
||||||
|
|
||||||
result := emptyValue
|
result := emptyValue
|
||||||
object := sourceObject
|
obj := sourceObject
|
||||||
for object != nil {
|
for obj != nil {
|
||||||
enumerateValue := emptyValue
|
enumerateValue := emptyValue
|
||||||
object.enumerate(false, func(name string) bool {
|
obj.enumerate(false, func(name string) bool {
|
||||||
into := self.cmpl_evaluate_nodeExpression(into)
|
into := rt.cmplEvaluateNodeExpression(into)
|
||||||
// In the case of: for (var abc in def) ...
|
// In the case of: for (var abc in def) ...
|
||||||
if into.reference() == nil {
|
if into.reference() == nil {
|
||||||
identifier := into.string()
|
identifier := into.string()
|
||||||
// TODO Should be true or false (strictness) depending on context
|
// TODO Should be true or false (strictness) depending on context
|
||||||
into = toValue(getIdentifierReference(self, self.scope.lexical, identifier, false, -1))
|
into = toValue(getIdentifierReference(rt, rt.scope.lexical, identifier, false, -1))
|
||||||
}
|
}
|
||||||
self.putValue(into.reference(), toValue_string(name))
|
rt.putValue(into.reference(), stringValue(name))
|
||||||
for _, node := range body {
|
for _, node := range body {
|
||||||
value := self.cmpl_evaluate_nodeStatement(node)
|
value := rt.cmplEvaluateNodeStatement(node)
|
||||||
switch value.kind {
|
switch value.kind {
|
||||||
case valueResult:
|
case valueResult:
|
||||||
switch value.evaluateBreakContinue(labels) {
|
switch value.evaluateBreakContinue(labels) {
|
||||||
|
@ -207,7 +207,7 @@ func (self *_runtime) cmpl_evaluate_nodeForInStatement(node *_nodeForInStatement
|
||||||
enumerateValue = value
|
enumerateValue = value
|
||||||
return false
|
return false
|
||||||
case resultBreak:
|
case resultBreak:
|
||||||
object = nil
|
obj = nil
|
||||||
return false
|
return false
|
||||||
case resultContinue:
|
case resultContinue:
|
||||||
return true
|
return true
|
||||||
|
@ -219,10 +219,10 @@ func (self *_runtime) cmpl_evaluate_nodeForInStatement(node *_nodeForInStatement
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
if object == nil {
|
if obj == nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
object = object.prototype
|
obj = obj.prototype
|
||||||
if !enumerateValue.isEmpty() {
|
if !enumerateValue.isEmpty() {
|
||||||
result = enumerateValue
|
result = enumerateValue
|
||||||
}
|
}
|
||||||
|
@ -230,9 +230,9 @@ func (self *_runtime) cmpl_evaluate_nodeForInStatement(node *_nodeForInStatement
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_runtime) cmpl_evaluate_nodeForStatement(node *_nodeForStatement) Value {
|
func (rt *runtime) cmplEvaluateNodeForStatement(node *nodeForStatement) Value {
|
||||||
labels := append(self.labels, "")
|
labels := append(rt.labels, "") //nolint: gocritic
|
||||||
self.labels = nil
|
rt.labels = nil
|
||||||
|
|
||||||
initializer := node.initializer
|
initializer := node.initializer
|
||||||
test := node.test
|
test := node.test
|
||||||
|
@ -240,7 +240,7 @@ func (self *_runtime) cmpl_evaluate_nodeForStatement(node *_nodeForStatement) Va
|
||||||
body := node.body
|
body := node.body
|
||||||
|
|
||||||
if initializer != nil {
|
if initializer != nil {
|
||||||
initialResult := self.cmpl_evaluate_nodeExpression(initializer)
|
initialResult := rt.cmplEvaluateNodeExpression(initializer)
|
||||||
initialResult.resolve() // Side-effect trigger
|
initialResult.resolve() // Side-effect trigger
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,25 +248,25 @@ func (self *_runtime) cmpl_evaluate_nodeForStatement(node *_nodeForStatement) Va
|
||||||
resultBreak:
|
resultBreak:
|
||||||
for {
|
for {
|
||||||
if test != nil {
|
if test != nil {
|
||||||
testResult := self.cmpl_evaluate_nodeExpression(test)
|
testResult := rt.cmplEvaluateNodeExpression(test)
|
||||||
testResultValue := testResult.resolve()
|
testResultValue := testResult.resolve()
|
||||||
if testResultValue.bool() == false {
|
if !testResultValue.bool() {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// this is to prevent for cycles with no body from running forever
|
// this is to prevent for cycles with no body from running forever
|
||||||
if len(body) == 0 && self.otto.Interrupt != nil {
|
if len(body) == 0 && rt.otto.Interrupt != nil {
|
||||||
runtime.Gosched()
|
goruntime.Gosched()
|
||||||
select {
|
select {
|
||||||
case value := <-self.otto.Interrupt:
|
case value := <-rt.otto.Interrupt:
|
||||||
value()
|
value()
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, node := range body {
|
for _, node := range body {
|
||||||
value := self.cmpl_evaluate_nodeStatement(node)
|
value := rt.cmplEvaluateNodeStatement(node)
|
||||||
switch value.kind {
|
switch value.kind {
|
||||||
case valueResult:
|
case valueResult:
|
||||||
switch value.evaluateBreakContinue(labels) {
|
switch value.evaluateBreakContinue(labels) {
|
||||||
|
@ -284,36 +284,36 @@ resultBreak:
|
||||||
}
|
}
|
||||||
resultContinue:
|
resultContinue:
|
||||||
if update != nil {
|
if update != nil {
|
||||||
updateResult := self.cmpl_evaluate_nodeExpression(update)
|
updateResult := rt.cmplEvaluateNodeExpression(update)
|
||||||
updateResult.resolve() // Side-effect trigger
|
updateResult.resolve() // Side-effect trigger
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_runtime) cmpl_evaluate_nodeIfStatement(node *_nodeIfStatement) Value {
|
func (rt *runtime) cmplEvaluateNodeIfStatement(node *nodeIfStatement) Value {
|
||||||
test := self.cmpl_evaluate_nodeExpression(node.test)
|
test := rt.cmplEvaluateNodeExpression(node.test)
|
||||||
testValue := test.resolve()
|
testValue := test.resolve()
|
||||||
if testValue.bool() {
|
if testValue.bool() {
|
||||||
return self.cmpl_evaluate_nodeStatement(node.consequent)
|
return rt.cmplEvaluateNodeStatement(node.consequent)
|
||||||
} else if node.alternate != nil {
|
} else if node.alternate != nil {
|
||||||
return self.cmpl_evaluate_nodeStatement(node.alternate)
|
return rt.cmplEvaluateNodeStatement(node.alternate)
|
||||||
}
|
}
|
||||||
|
|
||||||
return emptyValue
|
return emptyValue
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_runtime) cmpl_evaluate_nodeSwitchStatement(node *_nodeSwitchStatement) Value {
|
func (rt *runtime) cmplEvaluateNodeSwitchStatement(node *nodeSwitchStatement) Value {
|
||||||
labels := append(self.labels, "")
|
labels := append(rt.labels, "") //nolint: gocritic
|
||||||
self.labels = nil
|
rt.labels = nil
|
||||||
|
|
||||||
discriminantResult := self.cmpl_evaluate_nodeExpression(node.discriminant)
|
discriminantResult := rt.cmplEvaluateNodeExpression(node.discriminant)
|
||||||
target := node.default_
|
target := node.defaultIdx
|
||||||
|
|
||||||
for index, clause := range node.body {
|
for index, clause := range node.body {
|
||||||
test := clause.test
|
test := clause.test
|
||||||
if test != nil {
|
if test != nil {
|
||||||
if self.calculateComparison(token.STRICT_EQUAL, discriminantResult, self.cmpl_evaluate_nodeExpression(test)) {
|
if rt.calculateComparison(token.STRICT_EQUAL, discriminantResult, rt.cmplEvaluateNodeExpression(test)) {
|
||||||
target = index
|
target = index
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -324,7 +324,7 @@ func (self *_runtime) cmpl_evaluate_nodeSwitchStatement(node *_nodeSwitchStateme
|
||||||
if target != -1 {
|
if target != -1 {
|
||||||
for _, clause := range node.body[target:] {
|
for _, clause := range node.body[target:] {
|
||||||
for _, statement := range clause.consequent {
|
for _, statement := range clause.consequent {
|
||||||
value := self.cmpl_evaluate_nodeStatement(statement)
|
value := rt.cmplEvaluateNodeStatement(statement)
|
||||||
switch value.kind {
|
switch value.kind {
|
||||||
case valueResult:
|
case valueResult:
|
||||||
switch value.evaluateBreak(labels) {
|
switch value.evaluateBreak(labels) {
|
||||||
|
@ -344,58 +344,58 @@ func (self *_runtime) cmpl_evaluate_nodeSwitchStatement(node *_nodeSwitchStateme
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_runtime) cmpl_evaluate_nodeTryStatement(node *_nodeTryStatement) Value {
|
func (rt *runtime) cmplEvaluateNodeTryStatement(node *nodeTryStatement) Value {
|
||||||
tryCatchValue, exception := self.tryCatchEvaluate(func() Value {
|
tryCatchValue, exep := rt.tryCatchEvaluate(func() Value {
|
||||||
return self.cmpl_evaluate_nodeStatement(node.body)
|
return rt.cmplEvaluateNodeStatement(node.body)
|
||||||
})
|
})
|
||||||
|
|
||||||
if exception && node.catch != nil {
|
if exep && node.catch != nil {
|
||||||
outer := self.scope.lexical
|
outer := rt.scope.lexical
|
||||||
self.scope.lexical = self.newDeclarationStash(outer)
|
rt.scope.lexical = rt.newDeclarationStash(outer)
|
||||||
defer func() {
|
defer func() {
|
||||||
self.scope.lexical = outer
|
rt.scope.lexical = outer
|
||||||
}()
|
}()
|
||||||
// TODO If necessary, convert TypeError<runtime> => TypeError
|
// TODO If necessary, convert TypeError<runtime> => TypeError
|
||||||
// That, is, such errors can be thrown despite not being JavaScript "native"
|
// That, is, such errors can be thrown despite not being JavaScript "native"
|
||||||
// strict = false
|
// strict = false
|
||||||
self.scope.lexical.setValue(node.catch.parameter, tryCatchValue, false)
|
rt.scope.lexical.setValue(node.catch.parameter, tryCatchValue, false)
|
||||||
|
|
||||||
// FIXME node.CatchParameter
|
// FIXME node.CatchParameter
|
||||||
// FIXME node.Catch
|
// FIXME node.Catch
|
||||||
tryCatchValue, exception = self.tryCatchEvaluate(func() Value {
|
tryCatchValue, exep = rt.tryCatchEvaluate(func() Value {
|
||||||
return self.cmpl_evaluate_nodeStatement(node.catch.body)
|
return rt.cmplEvaluateNodeStatement(node.catch.body)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if node.finally != nil {
|
if node.finally != nil {
|
||||||
finallyValue := self.cmpl_evaluate_nodeStatement(node.finally)
|
finallyValue := rt.cmplEvaluateNodeStatement(node.finally)
|
||||||
if finallyValue.kind == valueResult {
|
if finallyValue.kind == valueResult {
|
||||||
return finallyValue
|
return finallyValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if exception {
|
if exep {
|
||||||
panic(newException(tryCatchValue))
|
panic(newException(tryCatchValue))
|
||||||
}
|
}
|
||||||
|
|
||||||
return tryCatchValue
|
return tryCatchValue
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_runtime) cmpl_evaluate_nodeWhileStatement(node *_nodeWhileStatement) Value {
|
func (rt *runtime) cmplEvaluateModeWhileStatement(node *nodeWhileStatement) Value {
|
||||||
test := node.test
|
test := node.test
|
||||||
body := node.body
|
body := node.body
|
||||||
labels := append(self.labels, "")
|
labels := append(rt.labels, "") //nolint: gocritic
|
||||||
self.labels = nil
|
rt.labels = nil
|
||||||
|
|
||||||
result := emptyValue
|
result := emptyValue
|
||||||
resultBreakContinue:
|
resultBreakContinue:
|
||||||
for {
|
for {
|
||||||
if !self.cmpl_evaluate_nodeExpression(test).resolve().bool() {
|
if !rt.cmplEvaluateNodeExpression(test).resolve().bool() {
|
||||||
// Stahp: while (false) ...
|
// Stahp: while (false) ...
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
for _, node := range body {
|
for _, node := range body {
|
||||||
value := self.cmpl_evaluate_nodeStatement(node)
|
value := rt.cmplEvaluateNodeStatement(node)
|
||||||
switch value.kind {
|
switch value.kind {
|
||||||
case valueResult:
|
case valueResult:
|
||||||
switch value.evaluateBreakContinue(labels) {
|
switch value.evaluateBreakContinue(labels) {
|
||||||
|
@ -415,14 +415,14 @@ resultBreakContinue:
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_runtime) cmpl_evaluate_nodeWithStatement(node *_nodeWithStatement) Value {
|
func (rt *runtime) cmplEvaluateNodeWithStatement(node *nodeWithStatement) Value {
|
||||||
object := self.cmpl_evaluate_nodeExpression(node.object)
|
obj := rt.cmplEvaluateNodeExpression(node.object)
|
||||||
outer := self.scope.lexical
|
outer := rt.scope.lexical
|
||||||
lexical := self.newObjectStash(self.toObject(object.resolve()), outer)
|
lexical := rt.newObjectStash(rt.toObject(obj.resolve()), outer)
|
||||||
self.scope.lexical = lexical
|
rt.scope.lexical = lexical
|
||||||
defer func() {
|
defer func() {
|
||||||
self.scope.lexical = outer
|
rt.scope.lexical = outer
|
||||||
}()
|
}()
|
||||||
|
|
||||||
return self.cmpl_evaluate_nodeStatement(node.body)
|
return rt.cmplEvaluateNodeStatement(node.body)
|
||||||
}
|
}
|
||||||
|
|
610
v1/vendor/github.com/robertkrimen/otto/cmpl_parse.go
generated
vendored
|
@ -2,83 +2,84 @@ package otto
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"regexp"
|
|
||||||
|
|
||||||
"github.com/robertkrimen/otto/ast"
|
"github.com/robertkrimen/otto/ast"
|
||||||
"github.com/robertkrimen/otto/file"
|
"github.com/robertkrimen/otto/file"
|
||||||
"github.com/robertkrimen/otto/token"
|
"github.com/robertkrimen/otto/token"
|
||||||
)
|
)
|
||||||
|
|
||||||
var trueLiteral = &_nodeLiteral{value: toValue_bool(true)}
|
var (
|
||||||
var falseLiteral = &_nodeLiteral{value: toValue_bool(false)}
|
trueLiteral = &nodeLiteral{value: boolValue(true)}
|
||||||
var nullLiteral = &_nodeLiteral{value: nullValue}
|
falseLiteral = &nodeLiteral{value: boolValue(false)}
|
||||||
var emptyStatement = &_nodeEmptyStatement{}
|
nullLiteral = &nodeLiteral{value: nullValue}
|
||||||
|
emptyStatement = &nodeEmptyStatement{}
|
||||||
|
)
|
||||||
|
|
||||||
func (cmpl *_compiler) parseExpression(in ast.Expression) _nodeExpression {
|
func (cmpl *compiler) parseExpression(expr ast.Expression) nodeExpression {
|
||||||
if in == nil {
|
if expr == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
switch in := in.(type) {
|
switch expr := expr.(type) {
|
||||||
case *ast.ArrayLiteral:
|
case *ast.ArrayLiteral:
|
||||||
out := &_nodeArrayLiteral{
|
out := &nodeArrayLiteral{
|
||||||
value: make([]_nodeExpression, len(in.Value)),
|
value: make([]nodeExpression, len(expr.Value)),
|
||||||
}
|
}
|
||||||
for i, value := range in.Value {
|
for i, value := range expr.Value {
|
||||||
out.value[i] = cmpl.parseExpression(value)
|
out.value[i] = cmpl.parseExpression(value)
|
||||||
}
|
}
|
||||||
return out
|
return out
|
||||||
|
|
||||||
case *ast.AssignExpression:
|
case *ast.AssignExpression:
|
||||||
return &_nodeAssignExpression{
|
return &nodeAssignExpression{
|
||||||
operator: in.Operator,
|
operator: expr.Operator,
|
||||||
left: cmpl.parseExpression(in.Left),
|
left: cmpl.parseExpression(expr.Left),
|
||||||
right: cmpl.parseExpression(in.Right),
|
right: cmpl.parseExpression(expr.Right),
|
||||||
}
|
}
|
||||||
|
|
||||||
case *ast.BinaryExpression:
|
case *ast.BinaryExpression:
|
||||||
return &_nodeBinaryExpression{
|
return &nodeBinaryExpression{
|
||||||
operator: in.Operator,
|
operator: expr.Operator,
|
||||||
left: cmpl.parseExpression(in.Left),
|
left: cmpl.parseExpression(expr.Left),
|
||||||
right: cmpl.parseExpression(in.Right),
|
right: cmpl.parseExpression(expr.Right),
|
||||||
comparison: in.Comparison,
|
comparison: expr.Comparison,
|
||||||
}
|
}
|
||||||
|
|
||||||
case *ast.BooleanLiteral:
|
case *ast.BooleanLiteral:
|
||||||
if in.Value {
|
if expr.Value {
|
||||||
return trueLiteral
|
return trueLiteral
|
||||||
}
|
}
|
||||||
return falseLiteral
|
return falseLiteral
|
||||||
|
|
||||||
case *ast.BracketExpression:
|
case *ast.BracketExpression:
|
||||||
return &_nodeBracketExpression{
|
return &nodeBracketExpression{
|
||||||
idx: in.Left.Idx0(),
|
idx: expr.Left.Idx0(),
|
||||||
left: cmpl.parseExpression(in.Left),
|
left: cmpl.parseExpression(expr.Left),
|
||||||
member: cmpl.parseExpression(in.Member),
|
member: cmpl.parseExpression(expr.Member),
|
||||||
}
|
}
|
||||||
|
|
||||||
case *ast.CallExpression:
|
case *ast.CallExpression:
|
||||||
out := &_nodeCallExpression{
|
out := &nodeCallExpression{
|
||||||
callee: cmpl.parseExpression(in.Callee),
|
callee: cmpl.parseExpression(expr.Callee),
|
||||||
argumentList: make([]_nodeExpression, len(in.ArgumentList)),
|
argumentList: make([]nodeExpression, len(expr.ArgumentList)),
|
||||||
}
|
}
|
||||||
for i, value := range in.ArgumentList {
|
for i, value := range expr.ArgumentList {
|
||||||
out.argumentList[i] = cmpl.parseExpression(value)
|
out.argumentList[i] = cmpl.parseExpression(value)
|
||||||
}
|
}
|
||||||
return out
|
return out
|
||||||
|
|
||||||
case *ast.ConditionalExpression:
|
case *ast.ConditionalExpression:
|
||||||
return &_nodeConditionalExpression{
|
return &nodeConditionalExpression{
|
||||||
test: cmpl.parseExpression(in.Test),
|
test: cmpl.parseExpression(expr.Test),
|
||||||
consequent: cmpl.parseExpression(in.Consequent),
|
consequent: cmpl.parseExpression(expr.Consequent),
|
||||||
alternate: cmpl.parseExpression(in.Alternate),
|
alternate: cmpl.parseExpression(expr.Alternate),
|
||||||
}
|
}
|
||||||
|
|
||||||
case *ast.DotExpression:
|
case *ast.DotExpression:
|
||||||
return &_nodeDotExpression{
|
return &nodeDotExpression{
|
||||||
idx: in.Left.Idx0(),
|
idx: expr.Left.Idx0(),
|
||||||
left: cmpl.parseExpression(in.Left),
|
left: cmpl.parseExpression(expr.Left),
|
||||||
identifier: in.Identifier.Name,
|
identifier: expr.Identifier.Name,
|
||||||
}
|
}
|
||||||
|
|
||||||
case *ast.EmptyExpression:
|
case *ast.EmptyExpression:
|
||||||
|
@ -86,48 +87,48 @@ func (cmpl *_compiler) parseExpression(in ast.Expression) _nodeExpression {
|
||||||
|
|
||||||
case *ast.FunctionLiteral:
|
case *ast.FunctionLiteral:
|
||||||
name := ""
|
name := ""
|
||||||
if in.Name != nil {
|
if expr.Name != nil {
|
||||||
name = in.Name.Name
|
name = expr.Name.Name
|
||||||
}
|
}
|
||||||
out := &_nodeFunctionLiteral{
|
out := &nodeFunctionLiteral{
|
||||||
name: name,
|
name: name,
|
||||||
body: cmpl.parseStatement(in.Body),
|
body: cmpl.parseStatement(expr.Body),
|
||||||
source: in.Source,
|
source: expr.Source,
|
||||||
file: cmpl.file,
|
file: cmpl.file,
|
||||||
}
|
}
|
||||||
if in.ParameterList != nil {
|
if expr.ParameterList != nil {
|
||||||
list := in.ParameterList.List
|
list := expr.ParameterList.List
|
||||||
out.parameterList = make([]string, len(list))
|
out.parameterList = make([]string, len(list))
|
||||||
for i, value := range list {
|
for i, value := range list {
|
||||||
out.parameterList[i] = value.Name
|
out.parameterList[i] = value.Name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, value := range in.DeclarationList {
|
for _, value := range expr.DeclarationList {
|
||||||
switch value := value.(type) {
|
switch value := value.(type) {
|
||||||
case *ast.FunctionDeclaration:
|
case *ast.FunctionDeclaration:
|
||||||
out.functionList = append(out.functionList, cmpl.parseExpression(value.Function).(*_nodeFunctionLiteral))
|
out.functionList = append(out.functionList, cmpl.parseExpression(value.Function).(*nodeFunctionLiteral))
|
||||||
case *ast.VariableDeclaration:
|
case *ast.VariableDeclaration:
|
||||||
for _, value := range value.List {
|
for _, value := range value.List {
|
||||||
out.varList = append(out.varList, value.Name)
|
out.varList = append(out.varList, value.Name)
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
panic(fmt.Errorf("Here be dragons: parseProgram.declaration(%T)", value))
|
panic(fmt.Sprintf("parse expression unknown function declaration type %T", value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return out
|
return out
|
||||||
|
|
||||||
case *ast.Identifier:
|
case *ast.Identifier:
|
||||||
return &_nodeIdentifier{
|
return &nodeIdentifier{
|
||||||
idx: in.Idx,
|
idx: expr.Idx,
|
||||||
name: in.Name,
|
name: expr.Name,
|
||||||
}
|
}
|
||||||
|
|
||||||
case *ast.NewExpression:
|
case *ast.NewExpression:
|
||||||
out := &_nodeNewExpression{
|
out := &nodeNewExpression{
|
||||||
callee: cmpl.parseExpression(in.Callee),
|
callee: cmpl.parseExpression(expr.Callee),
|
||||||
argumentList: make([]_nodeExpression, len(in.ArgumentList)),
|
argumentList: make([]nodeExpression, len(expr.ArgumentList)),
|
||||||
}
|
}
|
||||||
for i, value := range in.ArgumentList {
|
for i, value := range expr.ArgumentList {
|
||||||
out.argumentList[i] = cmpl.parseExpression(value)
|
out.argumentList[i] = cmpl.parseExpression(value)
|
||||||
}
|
}
|
||||||
return out
|
return out
|
||||||
|
@ -136,16 +137,16 @@ func (cmpl *_compiler) parseExpression(in ast.Expression) _nodeExpression {
|
||||||
return nullLiteral
|
return nullLiteral
|
||||||
|
|
||||||
case *ast.NumberLiteral:
|
case *ast.NumberLiteral:
|
||||||
return &_nodeLiteral{
|
return &nodeLiteral{
|
||||||
value: toValue(in.Value),
|
value: toValue(expr.Value),
|
||||||
}
|
}
|
||||||
|
|
||||||
case *ast.ObjectLiteral:
|
case *ast.ObjectLiteral:
|
||||||
out := &_nodeObjectLiteral{
|
out := &nodeObjectLiteral{
|
||||||
value: make([]_nodeProperty, len(in.Value)),
|
value: make([]nodeProperty, len(expr.Value)),
|
||||||
}
|
}
|
||||||
for i, value := range in.Value {
|
for i, value := range expr.Value {
|
||||||
out.value[i] = _nodeProperty{
|
out.value[i] = nodeProperty{
|
||||||
key: value.Key,
|
key: value.Key,
|
||||||
kind: value.Kind,
|
kind: value.Kind,
|
||||||
value: cmpl.parseExpression(value.Value),
|
value: cmpl.parseExpression(value.Value),
|
||||||
|
@ -154,79 +155,79 @@ func (cmpl *_compiler) parseExpression(in ast.Expression) _nodeExpression {
|
||||||
return out
|
return out
|
||||||
|
|
||||||
case *ast.RegExpLiteral:
|
case *ast.RegExpLiteral:
|
||||||
return &_nodeRegExpLiteral{
|
return &nodeRegExpLiteral{
|
||||||
flags: in.Flags,
|
flags: expr.Flags,
|
||||||
pattern: in.Pattern,
|
pattern: expr.Pattern,
|
||||||
}
|
}
|
||||||
|
|
||||||
case *ast.SequenceExpression:
|
case *ast.SequenceExpression:
|
||||||
out := &_nodeSequenceExpression{
|
out := &nodeSequenceExpression{
|
||||||
sequence: make([]_nodeExpression, len(in.Sequence)),
|
sequence: make([]nodeExpression, len(expr.Sequence)),
|
||||||
}
|
}
|
||||||
for i, value := range in.Sequence {
|
for i, value := range expr.Sequence {
|
||||||
out.sequence[i] = cmpl.parseExpression(value)
|
out.sequence[i] = cmpl.parseExpression(value)
|
||||||
}
|
}
|
||||||
return out
|
return out
|
||||||
|
|
||||||
case *ast.StringLiteral:
|
case *ast.StringLiteral:
|
||||||
return &_nodeLiteral{
|
return &nodeLiteral{
|
||||||
value: toValue_string(in.Value),
|
value: stringValue(expr.Value),
|
||||||
}
|
}
|
||||||
|
|
||||||
case *ast.ThisExpression:
|
case *ast.ThisExpression:
|
||||||
return &_nodeThisExpression{}
|
return &nodeThisExpression{}
|
||||||
|
|
||||||
case *ast.UnaryExpression:
|
case *ast.UnaryExpression:
|
||||||
return &_nodeUnaryExpression{
|
return &nodeUnaryExpression{
|
||||||
operator: in.Operator,
|
operator: expr.Operator,
|
||||||
operand: cmpl.parseExpression(in.Operand),
|
operand: cmpl.parseExpression(expr.Operand),
|
||||||
postfix: in.Postfix,
|
postfix: expr.Postfix,
|
||||||
}
|
}
|
||||||
|
|
||||||
case *ast.VariableExpression:
|
case *ast.VariableExpression:
|
||||||
return &_nodeVariableExpression{
|
return &nodeVariableExpression{
|
||||||
idx: in.Idx0(),
|
idx: expr.Idx0(),
|
||||||
name: in.Name,
|
name: expr.Name,
|
||||||
initializer: cmpl.parseExpression(in.Initializer),
|
initializer: cmpl.parseExpression(expr.Initializer),
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
panic(fmt.Errorf("parse expression unknown node type %T", expr))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
panic(fmt.Errorf("Here be dragons: cmpl.parseExpression(%T)", in))
|
func (cmpl *compiler) parseStatement(stmt ast.Statement) nodeStatement {
|
||||||
}
|
if stmt == nil {
|
||||||
|
|
||||||
func (cmpl *_compiler) parseStatement(in ast.Statement) _nodeStatement {
|
|
||||||
if in == nil {
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
switch in := in.(type) {
|
switch stmt := stmt.(type) {
|
||||||
case *ast.BlockStatement:
|
case *ast.BlockStatement:
|
||||||
out := &_nodeBlockStatement{
|
out := &nodeBlockStatement{
|
||||||
list: make([]_nodeStatement, len(in.List)),
|
list: make([]nodeStatement, len(stmt.List)),
|
||||||
}
|
}
|
||||||
for i, value := range in.List {
|
for i, value := range stmt.List {
|
||||||
out.list[i] = cmpl.parseStatement(value)
|
out.list[i] = cmpl.parseStatement(value)
|
||||||
}
|
}
|
||||||
return out
|
return out
|
||||||
|
|
||||||
case *ast.BranchStatement:
|
case *ast.BranchStatement:
|
||||||
out := &_nodeBranchStatement{
|
out := &nodeBranchStatement{
|
||||||
branch: in.Token,
|
branch: stmt.Token,
|
||||||
}
|
}
|
||||||
if in.Label != nil {
|
if stmt.Label != nil {
|
||||||
out.label = in.Label.Name
|
out.label = stmt.Label.Name
|
||||||
}
|
}
|
||||||
return out
|
return out
|
||||||
|
|
||||||
case *ast.DebuggerStatement:
|
case *ast.DebuggerStatement:
|
||||||
return &_nodeDebuggerStatement{}
|
return &nodeDebuggerStatement{}
|
||||||
|
|
||||||
case *ast.DoWhileStatement:
|
case *ast.DoWhileStatement:
|
||||||
out := &_nodeDoWhileStatement{
|
out := &nodeDoWhileStatement{
|
||||||
test: cmpl.parseExpression(in.Test),
|
test: cmpl.parseExpression(stmt.Test),
|
||||||
}
|
}
|
||||||
body := cmpl.parseStatement(in.Body)
|
body := cmpl.parseStatement(stmt.Body)
|
||||||
if block, ok := body.(*_nodeBlockStatement); ok {
|
if block, ok := body.(*nodeBlockStatement); ok {
|
||||||
out.body = block.list
|
out.body = block.list
|
||||||
} else {
|
} else {
|
||||||
out.body = append(out.body, body)
|
out.body = append(out.body, body)
|
||||||
|
@ -237,17 +238,17 @@ func (cmpl *_compiler) parseStatement(in ast.Statement) _nodeStatement {
|
||||||
return emptyStatement
|
return emptyStatement
|
||||||
|
|
||||||
case *ast.ExpressionStatement:
|
case *ast.ExpressionStatement:
|
||||||
return &_nodeExpressionStatement{
|
return &nodeExpressionStatement{
|
||||||
expression: cmpl.parseExpression(in.Expression),
|
expression: cmpl.parseExpression(stmt.Expression),
|
||||||
}
|
}
|
||||||
|
|
||||||
case *ast.ForInStatement:
|
case *ast.ForInStatement:
|
||||||
out := &_nodeForInStatement{
|
out := &nodeForInStatement{
|
||||||
into: cmpl.parseExpression(in.Into),
|
into: cmpl.parseExpression(stmt.Into),
|
||||||
source: cmpl.parseExpression(in.Source),
|
source: cmpl.parseExpression(stmt.Source),
|
||||||
}
|
}
|
||||||
body := cmpl.parseStatement(in.Body)
|
body := cmpl.parseStatement(stmt.Body)
|
||||||
if block, ok := body.(*_nodeBlockStatement); ok {
|
if block, ok := body.(*nodeBlockStatement); ok {
|
||||||
out.body = block.list
|
out.body = block.list
|
||||||
} else {
|
} else {
|
||||||
out.body = append(out.body, body)
|
out.body = append(out.body, body)
|
||||||
|
@ -255,13 +256,13 @@ func (cmpl *_compiler) parseStatement(in ast.Statement) _nodeStatement {
|
||||||
return out
|
return out
|
||||||
|
|
||||||
case *ast.ForStatement:
|
case *ast.ForStatement:
|
||||||
out := &_nodeForStatement{
|
out := &nodeForStatement{
|
||||||
initializer: cmpl.parseExpression(in.Initializer),
|
initializer: cmpl.parseExpression(stmt.Initializer),
|
||||||
update: cmpl.parseExpression(in.Update),
|
update: cmpl.parseExpression(stmt.Update),
|
||||||
test: cmpl.parseExpression(in.Test),
|
test: cmpl.parseExpression(stmt.Test),
|
||||||
}
|
}
|
||||||
body := cmpl.parseStatement(in.Body)
|
body := cmpl.parseStatement(stmt.Body)
|
||||||
if block, ok := body.(*_nodeBlockStatement); ok {
|
if block, ok := body.(*nodeBlockStatement); ok {
|
||||||
out.body = block.list
|
out.body = block.list
|
||||||
} else {
|
} else {
|
||||||
out.body = append(out.body, body)
|
out.body = append(out.body, body)
|
||||||
|
@ -272,33 +273,33 @@ func (cmpl *_compiler) parseStatement(in ast.Statement) _nodeStatement {
|
||||||
return emptyStatement
|
return emptyStatement
|
||||||
|
|
||||||
case *ast.IfStatement:
|
case *ast.IfStatement:
|
||||||
return &_nodeIfStatement{
|
return &nodeIfStatement{
|
||||||
test: cmpl.parseExpression(in.Test),
|
test: cmpl.parseExpression(stmt.Test),
|
||||||
consequent: cmpl.parseStatement(in.Consequent),
|
consequent: cmpl.parseStatement(stmt.Consequent),
|
||||||
alternate: cmpl.parseStatement(in.Alternate),
|
alternate: cmpl.parseStatement(stmt.Alternate),
|
||||||
}
|
}
|
||||||
|
|
||||||
case *ast.LabelledStatement:
|
case *ast.LabelledStatement:
|
||||||
return &_nodeLabelledStatement{
|
return &nodeLabelledStatement{
|
||||||
label: in.Label.Name,
|
label: stmt.Label.Name,
|
||||||
statement: cmpl.parseStatement(in.Statement),
|
statement: cmpl.parseStatement(stmt.Statement),
|
||||||
}
|
}
|
||||||
|
|
||||||
case *ast.ReturnStatement:
|
case *ast.ReturnStatement:
|
||||||
return &_nodeReturnStatement{
|
return &nodeReturnStatement{
|
||||||
argument: cmpl.parseExpression(in.Argument),
|
argument: cmpl.parseExpression(stmt.Argument),
|
||||||
}
|
}
|
||||||
|
|
||||||
case *ast.SwitchStatement:
|
case *ast.SwitchStatement:
|
||||||
out := &_nodeSwitchStatement{
|
out := &nodeSwitchStatement{
|
||||||
discriminant: cmpl.parseExpression(in.Discriminant),
|
discriminant: cmpl.parseExpression(stmt.Discriminant),
|
||||||
default_: in.Default,
|
defaultIdx: stmt.Default,
|
||||||
body: make([]*_nodeCaseStatement, len(in.Body)),
|
body: make([]*nodeCaseStatement, len(stmt.Body)),
|
||||||
}
|
}
|
||||||
for i, clause := range in.Body {
|
for i, clause := range stmt.Body {
|
||||||
out.body[i] = &_nodeCaseStatement{
|
out.body[i] = &nodeCaseStatement{
|
||||||
test: cmpl.parseExpression(clause.Test),
|
test: cmpl.parseExpression(clause.Test),
|
||||||
consequent: make([]_nodeStatement, len(clause.Consequent)),
|
consequent: make([]nodeStatement, len(clause.Consequent)),
|
||||||
}
|
}
|
||||||
for j, value := range clause.Consequent {
|
for j, value := range clause.Consequent {
|
||||||
out.body[i].consequent[j] = cmpl.parseStatement(value)
|
out.body[i].consequent[j] = cmpl.parseStatement(value)
|
||||||
|
@ -307,38 +308,38 @@ func (cmpl *_compiler) parseStatement(in ast.Statement) _nodeStatement {
|
||||||
return out
|
return out
|
||||||
|
|
||||||
case *ast.ThrowStatement:
|
case *ast.ThrowStatement:
|
||||||
return &_nodeThrowStatement{
|
return &nodeThrowStatement{
|
||||||
argument: cmpl.parseExpression(in.Argument),
|
argument: cmpl.parseExpression(stmt.Argument),
|
||||||
}
|
}
|
||||||
|
|
||||||
case *ast.TryStatement:
|
case *ast.TryStatement:
|
||||||
out := &_nodeTryStatement{
|
out := &nodeTryStatement{
|
||||||
body: cmpl.parseStatement(in.Body),
|
body: cmpl.parseStatement(stmt.Body),
|
||||||
finally: cmpl.parseStatement(in.Finally),
|
finally: cmpl.parseStatement(stmt.Finally),
|
||||||
}
|
}
|
||||||
if in.Catch != nil {
|
if stmt.Catch != nil {
|
||||||
out.catch = &_nodeCatchStatement{
|
out.catch = &nodeCatchStatement{
|
||||||
parameter: in.Catch.Parameter.Name,
|
parameter: stmt.Catch.Parameter.Name,
|
||||||
body: cmpl.parseStatement(in.Catch.Body),
|
body: cmpl.parseStatement(stmt.Catch.Body),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return out
|
return out
|
||||||
|
|
||||||
case *ast.VariableStatement:
|
case *ast.VariableStatement:
|
||||||
out := &_nodeVariableStatement{
|
out := &nodeVariableStatement{
|
||||||
list: make([]_nodeExpression, len(in.List)),
|
list: make([]nodeExpression, len(stmt.List)),
|
||||||
}
|
}
|
||||||
for i, value := range in.List {
|
for i, value := range stmt.List {
|
||||||
out.list[i] = cmpl.parseExpression(value)
|
out.list[i] = cmpl.parseExpression(value)
|
||||||
}
|
}
|
||||||
return out
|
return out
|
||||||
|
|
||||||
case *ast.WhileStatement:
|
case *ast.WhileStatement:
|
||||||
out := &_nodeWhileStatement{
|
out := &nodeWhileStatement{
|
||||||
test: cmpl.parseExpression(in.Test),
|
test: cmpl.parseExpression(stmt.Test),
|
||||||
}
|
}
|
||||||
body := cmpl.parseStatement(in.Body)
|
body := cmpl.parseStatement(stmt.Body)
|
||||||
if block, ok := body.(*_nodeBlockStatement); ok {
|
if block, ok := body.(*nodeBlockStatement); ok {
|
||||||
out.body = block.list
|
out.body = block.list
|
||||||
} else {
|
} else {
|
||||||
out.body = append(out.body, body)
|
out.body = append(out.body, body)
|
||||||
|
@ -346,307 +347,298 @@ func (cmpl *_compiler) parseStatement(in ast.Statement) _nodeStatement {
|
||||||
return out
|
return out
|
||||||
|
|
||||||
case *ast.WithStatement:
|
case *ast.WithStatement:
|
||||||
return &_nodeWithStatement{
|
return &nodeWithStatement{
|
||||||
object: cmpl.parseExpression(in.Object),
|
object: cmpl.parseExpression(stmt.Object),
|
||||||
body: cmpl.parseStatement(in.Body),
|
body: cmpl.parseStatement(stmt.Body),
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("parse statement: unknown type %T", stmt))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
panic(fmt.Errorf("Here be dragons: cmpl.parseStatement(%T)", in))
|
func cmplParse(in *ast.Program) *nodeProgram {
|
||||||
}
|
cmpl := compiler{
|
||||||
|
|
||||||
func cmpl_parse(in *ast.Program) *_nodeProgram {
|
|
||||||
cmpl := _compiler{
|
|
||||||
program: in,
|
program: in,
|
||||||
}
|
}
|
||||||
|
if cmpl.program != nil {
|
||||||
|
cmpl.file = cmpl.program.File
|
||||||
|
}
|
||||||
|
|
||||||
return cmpl.parse()
|
return cmpl.parse()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cmpl *_compiler) _parse(in *ast.Program) *_nodeProgram {
|
func (cmpl *compiler) parse() *nodeProgram {
|
||||||
out := &_nodeProgram{
|
out := &nodeProgram{
|
||||||
body: make([]_nodeStatement, len(in.Body)),
|
body: make([]nodeStatement, len(cmpl.program.Body)),
|
||||||
file: in.File,
|
file: cmpl.program.File,
|
||||||
}
|
}
|
||||||
for i, value := range in.Body {
|
for i, value := range cmpl.program.Body {
|
||||||
out.body[i] = cmpl.parseStatement(value)
|
out.body[i] = cmpl.parseStatement(value)
|
||||||
}
|
}
|
||||||
for _, value := range in.DeclarationList {
|
for _, value := range cmpl.program.DeclarationList {
|
||||||
switch value := value.(type) {
|
switch value := value.(type) {
|
||||||
case *ast.FunctionDeclaration:
|
case *ast.FunctionDeclaration:
|
||||||
out.functionList = append(out.functionList, cmpl.parseExpression(value.Function).(*_nodeFunctionLiteral))
|
out.functionList = append(out.functionList, cmpl.parseExpression(value.Function).(*nodeFunctionLiteral))
|
||||||
case *ast.VariableDeclaration:
|
case *ast.VariableDeclaration:
|
||||||
for _, value := range value.List {
|
for _, value := range value.List {
|
||||||
out.varList = append(out.varList, value.Name)
|
out.varList = append(out.varList, value.Name)
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
panic(fmt.Errorf("Here be dragons: cmpl.parseProgram.DeclarationList(%T)", value))
|
panic(fmt.Sprintf("Here be dragons: cmpl.parseProgram.DeclarationList(%T)", value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
type _nodeProgram struct {
|
type nodeProgram struct {
|
||||||
body []_nodeStatement
|
body []nodeStatement
|
||||||
|
|
||||||
varList []string
|
varList []string
|
||||||
functionList []*_nodeFunctionLiteral
|
functionList []*nodeFunctionLiteral
|
||||||
|
|
||||||
variableList []_nodeDeclaration
|
|
||||||
|
|
||||||
file *file.File
|
file *file.File
|
||||||
}
|
}
|
||||||
|
|
||||||
type _nodeDeclaration struct {
|
type node interface{}
|
||||||
name string
|
|
||||||
definition _node
|
|
||||||
}
|
|
||||||
|
|
||||||
type _node interface {
|
|
||||||
}
|
|
||||||
|
|
||||||
type (
|
type (
|
||||||
_nodeExpression interface {
|
nodeExpression interface {
|
||||||
_node
|
node
|
||||||
_expressionNode()
|
expressionNode()
|
||||||
}
|
}
|
||||||
|
|
||||||
_nodeArrayLiteral struct {
|
nodeArrayLiteral struct {
|
||||||
value []_nodeExpression
|
value []nodeExpression
|
||||||
}
|
}
|
||||||
|
|
||||||
_nodeAssignExpression struct {
|
nodeAssignExpression struct {
|
||||||
operator token.Token
|
operator token.Token
|
||||||
left _nodeExpression
|
left nodeExpression
|
||||||
right _nodeExpression
|
right nodeExpression
|
||||||
}
|
}
|
||||||
|
|
||||||
_nodeBinaryExpression struct {
|
nodeBinaryExpression struct {
|
||||||
operator token.Token
|
operator token.Token
|
||||||
left _nodeExpression
|
left nodeExpression
|
||||||
right _nodeExpression
|
right nodeExpression
|
||||||
comparison bool
|
comparison bool
|
||||||
}
|
}
|
||||||
|
|
||||||
_nodeBracketExpression struct {
|
nodeBracketExpression struct {
|
||||||
idx file.Idx
|
idx file.Idx
|
||||||
left _nodeExpression
|
left nodeExpression
|
||||||
member _nodeExpression
|
member nodeExpression
|
||||||
}
|
}
|
||||||
|
|
||||||
_nodeCallExpression struct {
|
nodeCallExpression struct {
|
||||||
callee _nodeExpression
|
callee nodeExpression
|
||||||
argumentList []_nodeExpression
|
argumentList []nodeExpression
|
||||||
}
|
}
|
||||||
|
|
||||||
_nodeConditionalExpression struct {
|
nodeConditionalExpression struct {
|
||||||
test _nodeExpression
|
test nodeExpression
|
||||||
consequent _nodeExpression
|
consequent nodeExpression
|
||||||
alternate _nodeExpression
|
alternate nodeExpression
|
||||||
}
|
}
|
||||||
|
|
||||||
_nodeDotExpression struct {
|
nodeDotExpression struct {
|
||||||
idx file.Idx
|
idx file.Idx
|
||||||
left _nodeExpression
|
left nodeExpression
|
||||||
identifier string
|
identifier string
|
||||||
}
|
}
|
||||||
|
|
||||||
_nodeFunctionLiteral struct {
|
nodeFunctionLiteral struct {
|
||||||
name string
|
name string
|
||||||
body _nodeStatement
|
body nodeStatement
|
||||||
source string
|
source string
|
||||||
parameterList []string
|
parameterList []string
|
||||||
varList []string
|
varList []string
|
||||||
functionList []*_nodeFunctionLiteral
|
functionList []*nodeFunctionLiteral
|
||||||
file *file.File
|
file *file.File
|
||||||
}
|
}
|
||||||
|
|
||||||
_nodeIdentifier struct {
|
nodeIdentifier struct {
|
||||||
idx file.Idx
|
idx file.Idx
|
||||||
name string
|
name string
|
||||||
}
|
}
|
||||||
|
|
||||||
_nodeLiteral struct {
|
nodeLiteral struct {
|
||||||
value Value
|
value Value
|
||||||
}
|
}
|
||||||
|
|
||||||
_nodeNewExpression struct {
|
nodeNewExpression struct {
|
||||||
callee _nodeExpression
|
callee nodeExpression
|
||||||
argumentList []_nodeExpression
|
argumentList []nodeExpression
|
||||||
}
|
}
|
||||||
|
|
||||||
_nodeObjectLiteral struct {
|
nodeObjectLiteral struct {
|
||||||
value []_nodeProperty
|
value []nodeProperty
|
||||||
}
|
}
|
||||||
|
|
||||||
_nodeProperty struct {
|
nodeProperty struct {
|
||||||
key string
|
key string
|
||||||
kind string
|
kind string
|
||||||
value _nodeExpression
|
value nodeExpression
|
||||||
}
|
}
|
||||||
|
|
||||||
_nodeRegExpLiteral struct {
|
nodeRegExpLiteral struct {
|
||||||
flags string
|
flags string
|
||||||
pattern string // Value?
|
pattern string // Value?
|
||||||
regexp *regexp.Regexp
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_nodeSequenceExpression struct {
|
nodeSequenceExpression struct {
|
||||||
sequence []_nodeExpression
|
sequence []nodeExpression
|
||||||
}
|
}
|
||||||
|
|
||||||
_nodeThisExpression struct {
|
nodeThisExpression struct{}
|
||||||
}
|
|
||||||
|
|
||||||
_nodeUnaryExpression struct {
|
nodeUnaryExpression struct {
|
||||||
operator token.Token
|
operator token.Token
|
||||||
operand _nodeExpression
|
operand nodeExpression
|
||||||
postfix bool
|
postfix bool
|
||||||
}
|
}
|
||||||
|
|
||||||
_nodeVariableExpression struct {
|
nodeVariableExpression struct {
|
||||||
idx file.Idx
|
idx file.Idx
|
||||||
name string
|
name string
|
||||||
initializer _nodeExpression
|
initializer nodeExpression
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
_nodeStatement interface {
|
nodeStatement interface {
|
||||||
_node
|
node
|
||||||
_statementNode()
|
statementNode()
|
||||||
}
|
}
|
||||||
|
|
||||||
_nodeBlockStatement struct {
|
nodeBlockStatement struct {
|
||||||
list []_nodeStatement
|
list []nodeStatement
|
||||||
}
|
}
|
||||||
|
|
||||||
_nodeBranchStatement struct {
|
nodeBranchStatement struct {
|
||||||
branch token.Token
|
branch token.Token
|
||||||
label string
|
label string
|
||||||
}
|
}
|
||||||
|
|
||||||
_nodeCaseStatement struct {
|
nodeCaseStatement struct {
|
||||||
test _nodeExpression
|
test nodeExpression
|
||||||
consequent []_nodeStatement
|
consequent []nodeStatement
|
||||||
}
|
}
|
||||||
|
|
||||||
_nodeCatchStatement struct {
|
nodeCatchStatement struct {
|
||||||
parameter string
|
parameter string
|
||||||
body _nodeStatement
|
body nodeStatement
|
||||||
}
|
}
|
||||||
|
|
||||||
_nodeDebuggerStatement struct {
|
nodeDebuggerStatement struct{}
|
||||||
|
|
||||||
|
nodeDoWhileStatement struct {
|
||||||
|
test nodeExpression
|
||||||
|
body []nodeStatement
|
||||||
}
|
}
|
||||||
|
|
||||||
_nodeDoWhileStatement struct {
|
nodeEmptyStatement struct{}
|
||||||
test _nodeExpression
|
|
||||||
body []_nodeStatement
|
nodeExpressionStatement struct {
|
||||||
|
expression nodeExpression
|
||||||
}
|
}
|
||||||
|
|
||||||
_nodeEmptyStatement struct {
|
nodeForInStatement struct {
|
||||||
|
into nodeExpression
|
||||||
|
source nodeExpression
|
||||||
|
body []nodeStatement
|
||||||
}
|
}
|
||||||
|
|
||||||
_nodeExpressionStatement struct {
|
nodeForStatement struct {
|
||||||
expression _nodeExpression
|
initializer nodeExpression
|
||||||
|
update nodeExpression
|
||||||
|
test nodeExpression
|
||||||
|
body []nodeStatement
|
||||||
}
|
}
|
||||||
|
|
||||||
_nodeForInStatement struct {
|
nodeIfStatement struct {
|
||||||
into _nodeExpression
|
test nodeExpression
|
||||||
source _nodeExpression
|
consequent nodeStatement
|
||||||
body []_nodeStatement
|
alternate nodeStatement
|
||||||
}
|
}
|
||||||
|
|
||||||
_nodeForStatement struct {
|
nodeLabelledStatement struct {
|
||||||
initializer _nodeExpression
|
|
||||||
update _nodeExpression
|
|
||||||
test _nodeExpression
|
|
||||||
body []_nodeStatement
|
|
||||||
}
|
|
||||||
|
|
||||||
_nodeIfStatement struct {
|
|
||||||
test _nodeExpression
|
|
||||||
consequent _nodeStatement
|
|
||||||
alternate _nodeStatement
|
|
||||||
}
|
|
||||||
|
|
||||||
_nodeLabelledStatement struct {
|
|
||||||
label string
|
label string
|
||||||
statement _nodeStatement
|
statement nodeStatement
|
||||||
}
|
}
|
||||||
|
|
||||||
_nodeReturnStatement struct {
|
nodeReturnStatement struct {
|
||||||
argument _nodeExpression
|
argument nodeExpression
|
||||||
}
|
}
|
||||||
|
|
||||||
_nodeSwitchStatement struct {
|
nodeSwitchStatement struct {
|
||||||
discriminant _nodeExpression
|
discriminant nodeExpression
|
||||||
default_ int
|
defaultIdx int
|
||||||
body []*_nodeCaseStatement
|
body []*nodeCaseStatement
|
||||||
}
|
}
|
||||||
|
|
||||||
_nodeThrowStatement struct {
|
nodeThrowStatement struct {
|
||||||
argument _nodeExpression
|
argument nodeExpression
|
||||||
}
|
}
|
||||||
|
|
||||||
_nodeTryStatement struct {
|
nodeTryStatement struct {
|
||||||
body _nodeStatement
|
body nodeStatement
|
||||||
catch *_nodeCatchStatement
|
catch *nodeCatchStatement
|
||||||
finally _nodeStatement
|
finally nodeStatement
|
||||||
}
|
}
|
||||||
|
|
||||||
_nodeVariableStatement struct {
|
nodeVariableStatement struct {
|
||||||
list []_nodeExpression
|
list []nodeExpression
|
||||||
}
|
}
|
||||||
|
|
||||||
_nodeWhileStatement struct {
|
nodeWhileStatement struct {
|
||||||
test _nodeExpression
|
test nodeExpression
|
||||||
body []_nodeStatement
|
body []nodeStatement
|
||||||
}
|
}
|
||||||
|
|
||||||
_nodeWithStatement struct {
|
nodeWithStatement struct {
|
||||||
object _nodeExpression
|
object nodeExpression
|
||||||
body _nodeStatement
|
body nodeStatement
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// _expressionNode
|
// expressionNode.
|
||||||
|
func (*nodeArrayLiteral) expressionNode() {}
|
||||||
|
func (*nodeAssignExpression) expressionNode() {}
|
||||||
|
func (*nodeBinaryExpression) expressionNode() {}
|
||||||
|
func (*nodeBracketExpression) expressionNode() {}
|
||||||
|
func (*nodeCallExpression) expressionNode() {}
|
||||||
|
func (*nodeConditionalExpression) expressionNode() {}
|
||||||
|
func (*nodeDotExpression) expressionNode() {}
|
||||||
|
func (*nodeFunctionLiteral) expressionNode() {}
|
||||||
|
func (*nodeIdentifier) expressionNode() {}
|
||||||
|
func (*nodeLiteral) expressionNode() {}
|
||||||
|
func (*nodeNewExpression) expressionNode() {}
|
||||||
|
func (*nodeObjectLiteral) expressionNode() {}
|
||||||
|
func (*nodeRegExpLiteral) expressionNode() {}
|
||||||
|
func (*nodeSequenceExpression) expressionNode() {}
|
||||||
|
func (*nodeThisExpression) expressionNode() {}
|
||||||
|
func (*nodeUnaryExpression) expressionNode() {}
|
||||||
|
func (*nodeVariableExpression) expressionNode() {}
|
||||||
|
|
||||||
func (*_nodeArrayLiteral) _expressionNode() {}
|
// statementNode
|
||||||
func (*_nodeAssignExpression) _expressionNode() {}
|
|
||||||
func (*_nodeBinaryExpression) _expressionNode() {}
|
|
||||||
func (*_nodeBracketExpression) _expressionNode() {}
|
|
||||||
func (*_nodeCallExpression) _expressionNode() {}
|
|
||||||
func (*_nodeConditionalExpression) _expressionNode() {}
|
|
||||||
func (*_nodeDotExpression) _expressionNode() {}
|
|
||||||
func (*_nodeFunctionLiteral) _expressionNode() {}
|
|
||||||
func (*_nodeIdentifier) _expressionNode() {}
|
|
||||||
func (*_nodeLiteral) _expressionNode() {}
|
|
||||||
func (*_nodeNewExpression) _expressionNode() {}
|
|
||||||
func (*_nodeObjectLiteral) _expressionNode() {}
|
|
||||||
func (*_nodeRegExpLiteral) _expressionNode() {}
|
|
||||||
func (*_nodeSequenceExpression) _expressionNode() {}
|
|
||||||
func (*_nodeThisExpression) _expressionNode() {}
|
|
||||||
func (*_nodeUnaryExpression) _expressionNode() {}
|
|
||||||
func (*_nodeVariableExpression) _expressionNode() {}
|
|
||||||
|
|
||||||
// _statementNode
|
func (*nodeBlockStatement) statementNode() {}
|
||||||
|
func (*nodeBranchStatement) statementNode() {}
|
||||||
func (*_nodeBlockStatement) _statementNode() {}
|
func (*nodeCaseStatement) statementNode() {}
|
||||||
func (*_nodeBranchStatement) _statementNode() {}
|
func (*nodeCatchStatement) statementNode() {}
|
||||||
func (*_nodeCaseStatement) _statementNode() {}
|
func (*nodeDebuggerStatement) statementNode() {}
|
||||||
func (*_nodeCatchStatement) _statementNode() {}
|
func (*nodeDoWhileStatement) statementNode() {}
|
||||||
func (*_nodeDebuggerStatement) _statementNode() {}
|
func (*nodeEmptyStatement) statementNode() {}
|
||||||
func (*_nodeDoWhileStatement) _statementNode() {}
|
func (*nodeExpressionStatement) statementNode() {}
|
||||||
func (*_nodeEmptyStatement) _statementNode() {}
|
func (*nodeForInStatement) statementNode() {}
|
||||||
func (*_nodeExpressionStatement) _statementNode() {}
|
func (*nodeForStatement) statementNode() {}
|
||||||
func (*_nodeForInStatement) _statementNode() {}
|
func (*nodeIfStatement) statementNode() {}
|
||||||
func (*_nodeForStatement) _statementNode() {}
|
func (*nodeLabelledStatement) statementNode() {}
|
||||||
func (*_nodeIfStatement) _statementNode() {}
|
func (*nodeReturnStatement) statementNode() {}
|
||||||
func (*_nodeLabelledStatement) _statementNode() {}
|
func (*nodeSwitchStatement) statementNode() {}
|
||||||
func (*_nodeReturnStatement) _statementNode() {}
|
func (*nodeThrowStatement) statementNode() {}
|
||||||
func (*_nodeSwitchStatement) _statementNode() {}
|
func (*nodeTryStatement) statementNode() {}
|
||||||
func (*_nodeThrowStatement) _statementNode() {}
|
func (*nodeVariableStatement) statementNode() {}
|
||||||
func (*_nodeTryStatement) _statementNode() {}
|
func (*nodeWhileStatement) statementNode() {}
|
||||||
func (*_nodeVariableStatement) _statementNode() {}
|
func (*nodeWithStatement) statementNode() {}
|
||||||
func (*_nodeWhileStatement) _statementNode() {}
|
|
||||||
func (*_nodeWithStatement) _statementNode() {}
|
|
||||||
|
|
18
v1/vendor/github.com/robertkrimen/otto/console.go
generated
vendored
|
@ -14,37 +14,33 @@ func formatForConsole(argumentList []Value) string {
|
||||||
return strings.Join(output, " ")
|
return strings.Join(output, " ")
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinConsole_log(call FunctionCall) Value {
|
func builtinConsoleLog(call FunctionCall) Value {
|
||||||
fmt.Fprintln(os.Stdout, formatForConsole(call.ArgumentList))
|
fmt.Fprintln(os.Stdout, formatForConsole(call.ArgumentList))
|
||||||
return Value{}
|
return Value{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinConsole_error(call FunctionCall) Value {
|
func builtinConsoleError(call FunctionCall) Value {
|
||||||
fmt.Fprintln(os.Stdout, formatForConsole(call.ArgumentList))
|
fmt.Fprintln(os.Stdout, formatForConsole(call.ArgumentList))
|
||||||
return Value{}
|
return Value{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Nothing happens.
|
// Nothing happens.
|
||||||
func builtinConsole_dir(call FunctionCall) Value {
|
func builtinConsoleDir(call FunctionCall) Value {
|
||||||
return Value{}
|
return Value{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinConsole_time(call FunctionCall) Value {
|
func builtinConsoleTime(call FunctionCall) Value {
|
||||||
return Value{}
|
return Value{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinConsole_timeEnd(call FunctionCall) Value {
|
func builtinConsoleTimeEnd(call FunctionCall) Value {
|
||||||
return Value{}
|
return Value{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinConsole_trace(call FunctionCall) Value {
|
func builtinConsoleTrace(call FunctionCall) Value {
|
||||||
return Value{}
|
return Value{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinConsole_assert(call FunctionCall) Value {
|
func builtinConsoleAssert(call FunctionCall) Value {
|
||||||
return Value{}
|
return Value{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (runtime *_runtime) newConsole() *_object {
|
|
||||||
return newConsoleObject(runtime)
|
|
||||||
}
|
|
||||||
|
|
38
v1/vendor/github.com/robertkrimen/otto/consts.go
generated
vendored
|
@ -2,18 +2,34 @@ package otto
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// Common classes.
|
// Common classes.
|
||||||
classString = "String"
|
classStringName = "String"
|
||||||
classGoArray = "GoArray"
|
classGoArrayName = "GoArray"
|
||||||
classGoSlice = "GoSlice"
|
classGoSliceName = "GoSlice"
|
||||||
classNumber = "Number"
|
classNumberName = "Number"
|
||||||
classDate = "Date"
|
classDateName = "Date"
|
||||||
classArray = "Array"
|
classArrayName = "Array"
|
||||||
classFunction = "Function"
|
classFunctionName = "Function"
|
||||||
classObject = "Object"
|
classObjectName = "Object"
|
||||||
classRegExp = "RegExp"
|
classRegExpName = "RegExp"
|
||||||
classBoolean = "Boolean"
|
classBooleanName = "Boolean"
|
||||||
classError = "Error"
|
classMathName = "Math"
|
||||||
|
classJSONName = "JSON"
|
||||||
|
|
||||||
|
// Error classes.
|
||||||
|
classErrorName = "Error"
|
||||||
|
classEvalErrorName = "EvalError"
|
||||||
|
classTypeErrorName = "TypeError"
|
||||||
|
classRangeErrorName = "RangeError"
|
||||||
|
classReferenceErrorName = "ReferenceError"
|
||||||
|
classSyntaxErrorName = "SyntaxError"
|
||||||
|
classURIErrorName = "URIError"
|
||||||
|
|
||||||
// Common properties.
|
// Common properties.
|
||||||
|
propertyName = "name"
|
||||||
propertyLength = "length"
|
propertyLength = "length"
|
||||||
|
propertyPrototype = "prototype"
|
||||||
|
propertyConstructor = "constructor"
|
||||||
|
|
||||||
|
// Common methods.
|
||||||
|
methodToString = "toString"
|
||||||
)
|
)
|
||||||
|
|
121
v1/vendor/github.com/robertkrimen/otto/dbg/dbg.go
generated
vendored
|
@ -52,7 +52,6 @@ a customization function:
|
||||||
dbg, dbgf := New(func(dbgr *Dbgr) {
|
dbg, dbgf := New(func(dbgr *Dbgr) {
|
||||||
dbgr.SetOutput(&buffer)
|
dbgr.SetOutput(&buffer)
|
||||||
})
|
})
|
||||||
|
|
||||||
*/
|
*/
|
||||||
package dbg
|
package dbg
|
||||||
|
|
||||||
|
@ -63,7 +62,7 @@ import (
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"regexp"
|
"regexp"
|
||||||
"runtime"
|
goruntime "runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"unicode"
|
"unicode"
|
||||||
)
|
)
|
||||||
|
@ -130,14 +129,13 @@ func parseFormat(format string) (frmt _frmt) {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Dbgr struct {
|
type Dbgr struct {
|
||||||
emit _emit
|
emit emit
|
||||||
}
|
}
|
||||||
|
|
||||||
type DbgFunction func(values ...interface{})
|
type DbgFunction func(values ...interface{})
|
||||||
|
|
||||||
func NewDbgr() *Dbgr {
|
func NewDbgr() *Dbgr {
|
||||||
self := &Dbgr{}
|
return &Dbgr{}
|
||||||
return self
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -153,7 +151,6 @@ they output to by passing in an (optional) customization function:
|
||||||
dbg, dbgf := Dbg.New(func(dbgr *Dbgr) {
|
dbg, dbgf := Dbg.New(func(dbgr *Dbgr) {
|
||||||
dbgr.SetOutput(os.Stderr)
|
dbgr.SetOutput(os.Stderr)
|
||||||
})
|
})
|
||||||
|
|
||||||
*/
|
*/
|
||||||
func New(options ...interface{}) (dbg DbgFunction, dbgf DbgFunction) {
|
func New(options ...interface{}) (dbg DbgFunction, dbgf DbgFunction) {
|
||||||
dbgr := NewDbgr()
|
dbgr := NewDbgr()
|
||||||
|
@ -165,26 +162,25 @@ func New(options ...interface{}) (dbg DbgFunction, dbgf DbgFunction) {
|
||||||
return dbgr.DbgDbgf()
|
return dbgr.DbgDbgf()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self Dbgr) Dbg(values ...interface{}) {
|
func (d Dbgr) Dbg(values ...interface{}) {
|
||||||
self.getEmit().emit(_frmt{}, "", values...)
|
d.getEmit().emit(_frmt{}, "", values...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self Dbgr) Dbgf(values ...interface{}) {
|
func (d Dbgr) Dbgf(values ...interface{}) {
|
||||||
self.dbgf(values...)
|
d.dbgf(values...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self Dbgr) DbgDbgf() (dbg DbgFunction, dbgf DbgFunction) {
|
func (d Dbgr) DbgDbgf() (dbg DbgFunction, dbgf DbgFunction) {
|
||||||
dbg = func(vl ...interface{}) {
|
dbg = func(vl ...interface{}) {
|
||||||
self.Dbg(vl...)
|
d.Dbg(vl...)
|
||||||
}
|
}
|
||||||
dbgf = func(vl ...interface{}) {
|
dbgf = func(vl ...interface{}) {
|
||||||
self.dbgf(vl...)
|
d.dbgf(vl...)
|
||||||
}
|
}
|
||||||
return dbg, dbgf // Redundant, but...
|
return dbg, dbgf // Redundant, but...
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self Dbgr) dbgf(values ...interface{}) {
|
func (d Dbgr) dbgf(values ...interface{}) {
|
||||||
|
|
||||||
var frmt _frmt
|
var frmt _frmt
|
||||||
if len(values) > 0 {
|
if len(values) > 0 {
|
||||||
tmp := fmt.Sprint(values[0])
|
tmp := fmt.Sprint(values[0])
|
||||||
|
@ -192,7 +188,7 @@ func (self Dbgr) dbgf(values ...interface{}) {
|
||||||
values = values[1:]
|
values = values[1:]
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer_f := bytes.Buffer{}
|
buf := bytes.Buffer{}
|
||||||
format := frmt.format
|
format := frmt.format
|
||||||
end := len(format)
|
end := len(format)
|
||||||
for at := 0; at < end; {
|
for at := 0; at < end; {
|
||||||
|
@ -201,7 +197,7 @@ func (self Dbgr) dbgf(values ...interface{}) {
|
||||||
at++
|
at++
|
||||||
}
|
}
|
||||||
if at > last {
|
if at > last {
|
||||||
buffer_f.WriteString(format[last:at])
|
buf.WriteString(format[last:at])
|
||||||
}
|
}
|
||||||
if at >= end {
|
if at >= end {
|
||||||
break
|
break
|
||||||
|
@ -211,72 +207,70 @@ func (self Dbgr) dbgf(values ...interface{}) {
|
||||||
// format[at] == ?
|
// format[at] == ?
|
||||||
if format[at] == '@' {
|
if format[at] == '@' {
|
||||||
depth := 2
|
depth := 2
|
||||||
pc, _, _, _ := runtime.Caller(depth)
|
pc, _, _, _ := goruntime.Caller(depth)
|
||||||
name := runtime.FuncForPC(pc).Name()
|
name := goruntime.FuncForPC(pc).Name()
|
||||||
buffer_f.WriteString(name)
|
buf.WriteString(name)
|
||||||
} else {
|
} else {
|
||||||
buffer_f.WriteString(format[at-1 : at+1])
|
buf.WriteString(format[at-1 : at+1])
|
||||||
}
|
}
|
||||||
at++
|
at++
|
||||||
}
|
}
|
||||||
|
|
||||||
//values_f := append([]interface{}{}, values[0:frmt.operandCount]...)
|
//valuesF := append([]interface{}{}, values[0:frmt.operandCount]...)
|
||||||
values_f := values[0:frmt.operandCount]
|
valuesF := values[0:frmt.operandCount]
|
||||||
values_dbg := values[frmt.operandCount:]
|
valuesDbg := values[frmt.operandCount:]
|
||||||
if len(values_dbg) > 0 {
|
if len(valuesDbg) > 0 {
|
||||||
// Adjust frmt.format:
|
// Adjust frmt.format:
|
||||||
// (%v instead of %s because: frmt.check)
|
// (%v instead of %s because: frmt.check)
|
||||||
{
|
|
||||||
tmp := format
|
tmp := format
|
||||||
if len(tmp) > 0 {
|
if len(tmp) > 0 {
|
||||||
if unicode.IsSpace(rune(tmp[len(tmp)-1])) {
|
if unicode.IsSpace(rune(tmp[len(tmp)-1])) {
|
||||||
buffer_f.WriteString("%v")
|
buf.WriteString("%v")
|
||||||
} else {
|
} else {
|
||||||
buffer_f.WriteString(" %v")
|
buf.WriteString(" %v")
|
||||||
}
|
}
|
||||||
} else if frmt.check {
|
} else if frmt.check {
|
||||||
// Performing a check, so no output
|
// Performing a check, so no output
|
||||||
} else {
|
} else {
|
||||||
buffer_f.WriteString("%v")
|
buf.WriteString("%v")
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adjust values_f:
|
// Adjust valuesF:
|
||||||
if !frmt.check {
|
if !frmt.check {
|
||||||
tmp := []string{}
|
tmp := []string{}
|
||||||
for _, value := range values_dbg {
|
for _, value := range valuesDbg {
|
||||||
tmp = append(tmp, fmt.Sprintf("%v", value))
|
tmp = append(tmp, fmt.Sprintf("%v", value))
|
||||||
}
|
}
|
||||||
// First, make a copy of values_f, so we avoid overwriting values_dbg when appending
|
// First, make a copy of valuesF, so we avoid overwriting valuesDbg when appending
|
||||||
values_f = append([]interface{}{}, values_f...)
|
valuesF = append([]interface{}{}, valuesF...)
|
||||||
values_f = append(values_f, strings.Join(tmp, " "))
|
valuesF = append(valuesF, strings.Join(tmp, " "))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
format = buffer_f.String()
|
format = buf.String()
|
||||||
if frmt.check {
|
if frmt.check {
|
||||||
// We do not actually emit to the log, but panic if
|
// We do not actually emit to the log, but panic if
|
||||||
// a non-nil value is detected (e.g. a non-nil error)
|
// a non-nil value is detected (e.g. a non-nil error)
|
||||||
for _, value := range values_dbg {
|
for _, value := range valuesDbg {
|
||||||
if value != nil {
|
if value != nil {
|
||||||
if format == "" {
|
if format == "" {
|
||||||
panic(value)
|
panic(value)
|
||||||
} else {
|
} else {
|
||||||
panic(fmt.Sprintf(format, append(values_f, value)...))
|
panic(fmt.Sprintf(format, append(valuesF, value)...))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.getEmit().emit(frmt, format, values_f...)
|
d.getEmit().emit(frmt, format, valuesF...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Idiot-proof &Dbgr{}, etc.
|
// Idiot-proof &Dbgr{}, etc.
|
||||||
func (self *Dbgr) getEmit() _emit {
|
func (d *Dbgr) getEmit() emit {
|
||||||
if self.emit == nil {
|
if d.emit == nil {
|
||||||
self.emit = standardEmit()
|
d.emit = standardEmit()
|
||||||
}
|
}
|
||||||
return self.emit
|
return d.emit
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetOutput will accept the following as a destination for output:
|
// SetOutput will accept the following as a destination for output:
|
||||||
|
@ -285,26 +279,25 @@ func (self *Dbgr) getEmit() _emit {
|
||||||
// io.Writer -
|
// io.Writer -
|
||||||
// nil Reset to the default output (os.Stderr)
|
// nil Reset to the default output (os.Stderr)
|
||||||
// "log" Print*/Panic*/Fatal* via the "log" package
|
// "log" Print*/Panic*/Fatal* via the "log" package
|
||||||
//
|
func (d *Dbgr) SetOutput(output interface{}) {
|
||||||
func (self *Dbgr) SetOutput(output interface{}) {
|
|
||||||
if output == nil {
|
if output == nil {
|
||||||
self.emit = standardEmit()
|
d.emit = standardEmit()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
switch output := output.(type) {
|
switch output := output.(type) {
|
||||||
case *log.Logger:
|
case *log.Logger:
|
||||||
self.emit = _emitLogger{
|
d.emit = emitLogger{
|
||||||
logger: output,
|
logger: output,
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
case io.Writer:
|
case io.Writer:
|
||||||
self.emit = _emitWriter{
|
d.emit = emitWriter{
|
||||||
writer: output,
|
writer: output,
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
case string:
|
case string:
|
||||||
if output == "log" {
|
if output == "log" {
|
||||||
self.emit = _emitLog{}
|
d.emit = emitLog{}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -315,8 +308,8 @@ func (self *Dbgr) SetOutput(output interface{}) {
|
||||||
// = emit = //
|
// = emit = //
|
||||||
// ======== //
|
// ======== //
|
||||||
|
|
||||||
func standardEmit() _emit {
|
func standardEmit() emit {
|
||||||
return _emitWriter{
|
return emitWriter{
|
||||||
writer: os.Stderr,
|
writer: os.Stderr,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -329,50 +322,50 @@ func ln(tmp string) string {
|
||||||
return tmp
|
return tmp
|
||||||
}
|
}
|
||||||
|
|
||||||
type _emit interface {
|
type emit interface {
|
||||||
emit(_frmt, string, ...interface{})
|
emit(_frmt, string, ...interface{})
|
||||||
}
|
}
|
||||||
|
|
||||||
type _emitWriter struct {
|
type emitWriter struct {
|
||||||
writer io.Writer
|
writer io.Writer
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self _emitWriter) emit(frmt _frmt, format string, values ...interface{}) {
|
func (ew emitWriter) emit(frmt _frmt, format string, values ...interface{}) {
|
||||||
if format == "" {
|
if format == "" {
|
||||||
fmt.Fprintln(self.writer, values...)
|
fmt.Fprintln(ew.writer, values...)
|
||||||
} else {
|
} else {
|
||||||
if frmt.panic {
|
if frmt.panic {
|
||||||
panic(fmt.Sprintf(format, values...))
|
panic(fmt.Sprintf(format, values...))
|
||||||
}
|
}
|
||||||
fmt.Fprintf(self.writer, ln(format), values...)
|
fmt.Fprintf(ew.writer, ln(format), values...)
|
||||||
if frmt.fatal {
|
if frmt.fatal {
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type _emitLogger struct {
|
type emitLogger struct {
|
||||||
logger *log.Logger
|
logger *log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self _emitLogger) emit(frmt _frmt, format string, values ...interface{}) {
|
func (el emitLogger) emit(frmt _frmt, format string, values ...interface{}) {
|
||||||
if format == "" {
|
if format == "" {
|
||||||
self.logger.Println(values...)
|
el.logger.Println(values...)
|
||||||
} else {
|
} else {
|
||||||
if frmt.panic {
|
if frmt.panic {
|
||||||
self.logger.Panicf(format, values...)
|
el.logger.Panicf(format, values...)
|
||||||
} else if frmt.fatal {
|
} else if frmt.fatal {
|
||||||
self.logger.Fatalf(format, values...)
|
el.logger.Fatalf(format, values...)
|
||||||
} else {
|
} else {
|
||||||
self.logger.Printf(format, values...)
|
el.logger.Printf(format, values...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type _emitLog struct {
|
type emitLog struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self _emitLog) emit(frmt _frmt, format string, values ...interface{}) {
|
func (el emitLog) emit(frmt _frmt, format string, values ...interface{}) {
|
||||||
if format == "" {
|
if format == "" {
|
||||||
log.Println(values...)
|
log.Println(values...)
|
||||||
} else {
|
} else {
|
||||||
|
|
133
v1/vendor/github.com/robertkrimen/otto/error.go
generated
vendored
|
@ -7,49 +7,49 @@ import (
|
||||||
"github.com/robertkrimen/otto/file"
|
"github.com/robertkrimen/otto/file"
|
||||||
)
|
)
|
||||||
|
|
||||||
type _exception struct {
|
type exception struct {
|
||||||
value interface{}
|
value interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newException(value interface{}) *_exception {
|
func newException(value interface{}) *exception {
|
||||||
return &_exception{
|
return &exception{
|
||||||
value: value,
|
value: value,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_exception) eject() interface{} {
|
func (e *exception) eject() interface{} {
|
||||||
value := self.value
|
value := e.value
|
||||||
self.value = nil // Prevent Go from holding on to the value, whatever it is
|
e.value = nil // Prevent Go from holding on to the value, whatever it is
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
|
|
||||||
type _error struct {
|
type ottoError struct {
|
||||||
name string
|
name string
|
||||||
message string
|
message string
|
||||||
trace []_frame
|
trace []frame
|
||||||
|
|
||||||
offset int
|
offset int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (err _error) format() string {
|
func (e ottoError) format() string {
|
||||||
if len(err.name) == 0 {
|
if len(e.name) == 0 {
|
||||||
return err.message
|
return e.message
|
||||||
}
|
}
|
||||||
if len(err.message) == 0 {
|
if len(e.message) == 0 {
|
||||||
return err.name
|
return e.name
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("%s: %s", err.name, err.message)
|
return fmt.Sprintf("%s: %s", e.name, e.message)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (err _error) formatWithStack() string {
|
func (e ottoError) formatWithStack() string {
|
||||||
str := err.format() + "\n"
|
str := e.format() + "\n"
|
||||||
for _, frame := range err.trace {
|
for _, frm := range e.trace {
|
||||||
str += " at " + frame.location() + "\n"
|
str += " at " + frm.location() + "\n"
|
||||||
}
|
}
|
||||||
return str
|
return str
|
||||||
}
|
}
|
||||||
|
|
||||||
type _frame struct {
|
type frame struct {
|
||||||
native bool
|
native bool
|
||||||
nativeFile string
|
nativeFile string
|
||||||
nativeLine int
|
nativeLine int
|
||||||
|
@ -59,13 +59,11 @@ type _frame struct {
|
||||||
fn interface{}
|
fn interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var nativeFrame = frame{}
|
||||||
nativeFrame = _frame{}
|
|
||||||
)
|
|
||||||
|
|
||||||
type _at int
|
type at int
|
||||||
|
|
||||||
func (fr _frame) location() string {
|
func (fr frame) location() string {
|
||||||
str := "<unknown>"
|
str := "<unknown>"
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
|
@ -95,14 +93,14 @@ func (fr _frame) location() string {
|
||||||
|
|
||||||
// An Error represents a runtime error, e.g. a TypeError, a ReferenceError, etc.
|
// An Error represents a runtime error, e.g. a TypeError, a ReferenceError, etc.
|
||||||
type Error struct {
|
type Error struct {
|
||||||
_error
|
ottoError
|
||||||
}
|
}
|
||||||
|
|
||||||
// Error returns a description of the error
|
// Error returns a description of the error
|
||||||
//
|
//
|
||||||
// TypeError: 'def' is not a function
|
// TypeError: 'def' is not a function
|
||||||
func (err Error) Error() string {
|
func (e Error) Error() string {
|
||||||
return err.format()
|
return e.format()
|
||||||
}
|
}
|
||||||
|
|
||||||
// String returns a description of the error and a trace of where the
|
// String returns a description of the error and a trace of where the
|
||||||
|
@ -111,36 +109,36 @@ func (err Error) Error() string {
|
||||||
// TypeError: 'def' is not a function
|
// TypeError: 'def' is not a function
|
||||||
// at xyz (<anonymous>:3:9)
|
// at xyz (<anonymous>:3:9)
|
||||||
// at <anonymous>:7:1/
|
// at <anonymous>:7:1/
|
||||||
func (err Error) String() string {
|
func (e Error) String() string {
|
||||||
return err.formatWithStack()
|
return e.formatWithStack()
|
||||||
}
|
}
|
||||||
|
|
||||||
// GoString returns a description of the error and a trace of where the
|
// GoString returns a description of the error and a trace of where the
|
||||||
// error occurred. Printing with %#v will trigger this behaviour.
|
// error occurred. Printing with %#v will trigger this behaviour.
|
||||||
func (err Error) GoString() string {
|
func (e Error) GoString() string {
|
||||||
return err.formatWithStack()
|
return e.formatWithStack()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (err _error) describe(format string, in ...interface{}) string {
|
func (e ottoError) describe(format string, in ...interface{}) string {
|
||||||
return fmt.Sprintf(format, in...)
|
return fmt.Sprintf(format, in...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self _error) messageValue() Value {
|
func (e ottoError) messageValue() Value {
|
||||||
if self.message == "" {
|
if e.message == "" {
|
||||||
return Value{}
|
return Value{}
|
||||||
}
|
}
|
||||||
return toValue_string(self.message)
|
return stringValue(e.message)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rt *_runtime) typeErrorResult(throw bool) bool {
|
func (rt *runtime) typeErrorResult(throw bool) bool {
|
||||||
if throw {
|
if throw {
|
||||||
panic(rt.panicTypeError())
|
panic(rt.panicTypeError())
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func newError(rt *_runtime, name string, stackFramesToPop int, in ...interface{}) _error {
|
func newError(rt *runtime, name string, stackFramesToPop int, in ...interface{}) ottoError {
|
||||||
err := _error{
|
err := ottoError{
|
||||||
name: name,
|
name: name,
|
||||||
offset: -1,
|
offset: -1,
|
||||||
}
|
}
|
||||||
|
@ -148,21 +146,21 @@ func newError(rt *_runtime, name string, stackFramesToPop int, in ...interface{}
|
||||||
length := len(in)
|
length := len(in)
|
||||||
|
|
||||||
if rt != nil && rt.scope != nil {
|
if rt != nil && rt.scope != nil {
|
||||||
scope := rt.scope
|
curScope := rt.scope
|
||||||
|
|
||||||
for i := 0; i < stackFramesToPop; i++ {
|
for i := 0; i < stackFramesToPop; i++ {
|
||||||
if scope.outer != nil {
|
if curScope.outer != nil {
|
||||||
scope = scope.outer
|
curScope = curScope.outer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
frame := scope.frame
|
frm := curScope.frame
|
||||||
|
|
||||||
if length > 0 {
|
if length > 0 {
|
||||||
if at, ok := in[length-1].(_at); ok {
|
if atv, ok := in[length-1].(at); ok {
|
||||||
in = in[0 : length-1]
|
in = in[0 : length-1]
|
||||||
if scope != nil {
|
if curScope != nil {
|
||||||
frame.offset = int(at)
|
frm.offset = int(atv)
|
||||||
}
|
}
|
||||||
length--
|
length--
|
||||||
}
|
}
|
||||||
|
@ -173,54 +171,52 @@ func newError(rt *_runtime, name string, stackFramesToPop int, in ...interface{}
|
||||||
|
|
||||||
limit := rt.traceLimit
|
limit := rt.traceLimit
|
||||||
|
|
||||||
err.trace = append(err.trace, frame)
|
err.trace = append(err.trace, frm)
|
||||||
if scope != nil {
|
if curScope != nil {
|
||||||
for scope = scope.outer; scope != nil; scope = scope.outer {
|
for curScope = curScope.outer; curScope != nil; curScope = curScope.outer {
|
||||||
if limit--; limit == 0 {
|
if limit--; limit == 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
if scope.frame.offset >= 0 {
|
if curScope.frame.offset >= 0 {
|
||||||
err.trace = append(err.trace, scope.frame)
|
err.trace = append(err.trace, curScope.frame)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else if length > 0 {
|
||||||
if length > 0 {
|
|
||||||
description, in = in[0].(string), in[1:]
|
description, in = in[0].(string), in[1:]
|
||||||
}
|
}
|
||||||
}
|
|
||||||
err.message = err.describe(description, in...)
|
err.message = err.describe(description, in...)
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rt *_runtime) panicTypeError(argumentList ...interface{}) *_exception {
|
func (rt *runtime) panicTypeError(argumentList ...interface{}) *exception {
|
||||||
return &_exception{
|
return &exception{
|
||||||
value: newError(rt, "TypeError", 0, argumentList...),
|
value: newError(rt, "TypeError", 0, argumentList...),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rt *_runtime) panicReferenceError(argumentList ...interface{}) *_exception {
|
func (rt *runtime) panicReferenceError(argumentList ...interface{}) *exception {
|
||||||
return &_exception{
|
return &exception{
|
||||||
value: newError(rt, "ReferenceError", 0, argumentList...),
|
value: newError(rt, "ReferenceError", 0, argumentList...),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rt *_runtime) panicURIError(argumentList ...interface{}) *_exception {
|
func (rt *runtime) panicURIError(argumentList ...interface{}) *exception {
|
||||||
return &_exception{
|
return &exception{
|
||||||
value: newError(rt, "URIError", 0, argumentList...),
|
value: newError(rt, "URIError", 0, argumentList...),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rt *_runtime) panicSyntaxError(argumentList ...interface{}) *_exception {
|
func (rt *runtime) panicSyntaxError(argumentList ...interface{}) *exception {
|
||||||
return &_exception{
|
return &exception{
|
||||||
value: newError(rt, "SyntaxError", 0, argumentList...),
|
value: newError(rt, "SyntaxError", 0, argumentList...),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rt *_runtime) panicRangeError(argumentList ...interface{}) *_exception {
|
func (rt *runtime) panicRangeError(argumentList ...interface{}) *exception {
|
||||||
return &_exception{
|
return &exception{
|
||||||
value: newError(rt, "RangeError", 0, argumentList...),
|
value: newError(rt, "RangeError", 0, argumentList...),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -228,20 +224,19 @@ func (rt *_runtime) panicRangeError(argumentList ...interface{}) *_exception {
|
||||||
func catchPanic(function func()) (err error) {
|
func catchPanic(function func()) (err error) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if caught := recover(); caught != nil {
|
if caught := recover(); caught != nil {
|
||||||
if exception, ok := caught.(*_exception); ok {
|
if excep, ok := caught.(*exception); ok {
|
||||||
caught = exception.eject()
|
caught = excep.eject()
|
||||||
}
|
}
|
||||||
switch caught := caught.(type) {
|
switch caught := caught.(type) {
|
||||||
case *Error:
|
case *Error:
|
||||||
err = caught
|
err = caught
|
||||||
return
|
return
|
||||||
case _error:
|
case ottoError:
|
||||||
err = &Error{caught}
|
err = &Error{caught}
|
||||||
return
|
return
|
||||||
case Value:
|
case Value:
|
||||||
if vl := caught._object(); vl != nil {
|
if vl := caught.object(); vl != nil {
|
||||||
switch vl := vl.value.(type) {
|
if vl, ok := vl.value.(ottoError); ok {
|
||||||
case _error:
|
|
||||||
err = &Error{vl}
|
err = &Error{vl}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
117
v1/vendor/github.com/robertkrimen/otto/evaluate.go
generated
vendored
|
@ -8,12 +8,12 @@ import (
|
||||||
"github.com/robertkrimen/otto/token"
|
"github.com/robertkrimen/otto/token"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (self *_runtime) evaluateMultiply(left float64, right float64) Value {
|
func (rt *runtime) evaluateMultiply(left float64, right float64) Value { //nolint: unused
|
||||||
// TODO 11.5.1
|
// TODO 11.5.1
|
||||||
return Value{}
|
return Value{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_runtime) evaluateDivide(left float64, right float64) Value {
|
func (rt *runtime) evaluateDivide(left float64, right float64) Value {
|
||||||
if math.IsNaN(left) || math.IsNaN(right) {
|
if math.IsNaN(left) || math.IsNaN(right) {
|
||||||
return NaNValue()
|
return NaNValue()
|
||||||
}
|
}
|
||||||
|
@ -26,61 +26,57 @@ func (self *_runtime) evaluateDivide(left float64, right float64) Value {
|
||||||
if math.IsInf(left, 0) {
|
if math.IsInf(left, 0) {
|
||||||
if math.Signbit(left) == math.Signbit(right) {
|
if math.Signbit(left) == math.Signbit(right) {
|
||||||
return positiveInfinityValue()
|
return positiveInfinityValue()
|
||||||
} else {
|
|
||||||
return negativeInfinityValue()
|
|
||||||
}
|
}
|
||||||
|
return negativeInfinityValue()
|
||||||
}
|
}
|
||||||
if math.IsInf(right, 0) {
|
if math.IsInf(right, 0) {
|
||||||
if math.Signbit(left) == math.Signbit(right) {
|
if math.Signbit(left) == math.Signbit(right) {
|
||||||
return positiveZeroValue()
|
return positiveZeroValue()
|
||||||
} else {
|
|
||||||
return negativeZeroValue()
|
|
||||||
}
|
}
|
||||||
|
return negativeZeroValue()
|
||||||
}
|
}
|
||||||
if right == 0 {
|
if right == 0 {
|
||||||
if math.Signbit(left) == math.Signbit(right) {
|
if math.Signbit(left) == math.Signbit(right) {
|
||||||
return positiveInfinityValue()
|
return positiveInfinityValue()
|
||||||
} else {
|
}
|
||||||
return negativeInfinityValue()
|
return negativeInfinityValue()
|
||||||
}
|
}
|
||||||
}
|
return float64Value(left / right)
|
||||||
return toValue_float64(left / right)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_runtime) evaluateModulo(left float64, right float64) Value {
|
func (rt *runtime) evaluateModulo(left float64, right float64) Value { //nolint: unused
|
||||||
// TODO 11.5.3
|
// TODO 11.5.3
|
||||||
return Value{}
|
return Value{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_runtime) calculateBinaryExpression(operator token.Token, left Value, right Value) Value {
|
func (rt *runtime) calculateBinaryExpression(operator token.Token, left Value, right Value) Value {
|
||||||
leftValue := left.resolve()
|
leftValue := left.resolve()
|
||||||
|
|
||||||
switch operator {
|
switch operator {
|
||||||
// Additive
|
// Additive
|
||||||
case token.PLUS:
|
case token.PLUS:
|
||||||
leftValue = toPrimitive(leftValue)
|
leftValue = toPrimitiveValue(leftValue)
|
||||||
rightValue := right.resolve()
|
rightValue := right.resolve()
|
||||||
rightValue = toPrimitive(rightValue)
|
rightValue = toPrimitiveValue(rightValue)
|
||||||
|
|
||||||
if leftValue.IsString() || rightValue.IsString() {
|
if leftValue.IsString() || rightValue.IsString() {
|
||||||
return toValue_string(strings.Join([]string{leftValue.string(), rightValue.string()}, ""))
|
return stringValue(strings.Join([]string{leftValue.string(), rightValue.string()}, ""))
|
||||||
} else {
|
|
||||||
return toValue_float64(leftValue.float64() + rightValue.float64())
|
|
||||||
}
|
}
|
||||||
|
return float64Value(leftValue.float64() + rightValue.float64())
|
||||||
case token.MINUS:
|
case token.MINUS:
|
||||||
rightValue := right.resolve()
|
rightValue := right.resolve()
|
||||||
return toValue_float64(leftValue.float64() - rightValue.float64())
|
return float64Value(leftValue.float64() - rightValue.float64())
|
||||||
|
|
||||||
// Multiplicative
|
// Multiplicative
|
||||||
case token.MULTIPLY:
|
case token.MULTIPLY:
|
||||||
rightValue := right.resolve()
|
rightValue := right.resolve()
|
||||||
return toValue_float64(leftValue.float64() * rightValue.float64())
|
return float64Value(leftValue.float64() * rightValue.float64())
|
||||||
case token.SLASH:
|
case token.SLASH:
|
||||||
rightValue := right.resolve()
|
rightValue := right.resolve()
|
||||||
return self.evaluateDivide(leftValue.float64(), rightValue.float64())
|
return rt.evaluateDivide(leftValue.float64(), rightValue.float64())
|
||||||
case token.REMAINDER:
|
case token.REMAINDER:
|
||||||
rightValue := right.resolve()
|
rightValue := right.resolve()
|
||||||
return toValue_float64(math.Mod(leftValue.float64(), rightValue.float64()))
|
return float64Value(math.Mod(leftValue.float64(), rightValue.float64()))
|
||||||
|
|
||||||
// Logical
|
// Logical
|
||||||
case token.LOGICAL_AND:
|
case token.LOGICAL_AND:
|
||||||
|
@ -88,65 +84,65 @@ func (self *_runtime) calculateBinaryExpression(operator token.Token, left Value
|
||||||
if !left {
|
if !left {
|
||||||
return falseValue
|
return falseValue
|
||||||
}
|
}
|
||||||
return toValue_bool(right.resolve().bool())
|
return boolValue(right.resolve().bool())
|
||||||
case token.LOGICAL_OR:
|
case token.LOGICAL_OR:
|
||||||
left := leftValue.bool()
|
left := leftValue.bool()
|
||||||
if left {
|
if left {
|
||||||
return trueValue
|
return trueValue
|
||||||
}
|
}
|
||||||
return toValue_bool(right.resolve().bool())
|
return boolValue(right.resolve().bool())
|
||||||
|
|
||||||
// Bitwise
|
// Bitwise
|
||||||
case token.AND:
|
case token.AND:
|
||||||
rightValue := right.resolve()
|
rightValue := right.resolve()
|
||||||
return toValue_int32(toInt32(leftValue) & toInt32(rightValue))
|
return int32Value(toInt32(leftValue) & toInt32(rightValue))
|
||||||
case token.OR:
|
case token.OR:
|
||||||
rightValue := right.resolve()
|
rightValue := right.resolve()
|
||||||
return toValue_int32(toInt32(leftValue) | toInt32(rightValue))
|
return int32Value(toInt32(leftValue) | toInt32(rightValue))
|
||||||
case token.EXCLUSIVE_OR:
|
case token.EXCLUSIVE_OR:
|
||||||
rightValue := right.resolve()
|
rightValue := right.resolve()
|
||||||
return toValue_int32(toInt32(leftValue) ^ toInt32(rightValue))
|
return int32Value(toInt32(leftValue) ^ toInt32(rightValue))
|
||||||
|
|
||||||
// Shift
|
// Shift
|
||||||
// (Masking of 0x1f is to restrict the shift to a maximum of 31 places)
|
// (Masking of 0x1f is to restrict the shift to a maximum of 31 places)
|
||||||
case token.SHIFT_LEFT:
|
case token.SHIFT_LEFT:
|
||||||
rightValue := right.resolve()
|
rightValue := right.resolve()
|
||||||
return toValue_int32(toInt32(leftValue) << (toUint32(rightValue) & 0x1f))
|
return int32Value(toInt32(leftValue) << (toUint32(rightValue) & 0x1f))
|
||||||
case token.SHIFT_RIGHT:
|
case token.SHIFT_RIGHT:
|
||||||
rightValue := right.resolve()
|
rightValue := right.resolve()
|
||||||
return toValue_int32(toInt32(leftValue) >> (toUint32(rightValue) & 0x1f))
|
return int32Value(toInt32(leftValue) >> (toUint32(rightValue) & 0x1f))
|
||||||
case token.UNSIGNED_SHIFT_RIGHT:
|
case token.UNSIGNED_SHIFT_RIGHT:
|
||||||
rightValue := right.resolve()
|
rightValue := right.resolve()
|
||||||
// Shifting an unsigned integer is a logical shift
|
// Shifting an unsigned integer is a logical shift
|
||||||
return toValue_uint32(toUint32(leftValue) >> (toUint32(rightValue) & 0x1f))
|
return uint32Value(toUint32(leftValue) >> (toUint32(rightValue) & 0x1f))
|
||||||
|
|
||||||
case token.INSTANCEOF:
|
case token.INSTANCEOF:
|
||||||
rightValue := right.resolve()
|
rightValue := right.resolve()
|
||||||
if !rightValue.IsObject() {
|
if !rightValue.IsObject() {
|
||||||
panic(self.panicTypeError("Expecting a function in instanceof check, but got: %v", rightValue))
|
panic(rt.panicTypeError("invalid kind %s for instanceof (expected object)", rightValue.kind))
|
||||||
}
|
}
|
||||||
return toValue_bool(rightValue._object().hasInstance(leftValue))
|
return boolValue(rightValue.object().hasInstance(leftValue))
|
||||||
|
|
||||||
case token.IN:
|
case token.IN:
|
||||||
rightValue := right.resolve()
|
rightValue := right.resolve()
|
||||||
if !rightValue.IsObject() {
|
if !rightValue.IsObject() {
|
||||||
panic(self.panicTypeError())
|
panic(rt.panicTypeError("invalid kind %s for in (expected object)", rightValue.kind))
|
||||||
}
|
}
|
||||||
return toValue_bool(rightValue._object().hasProperty(leftValue.string()))
|
return boolValue(rightValue.object().hasProperty(leftValue.string()))
|
||||||
}
|
}
|
||||||
|
|
||||||
panic(hereBeDragons(operator))
|
panic(hereBeDragons(operator))
|
||||||
}
|
}
|
||||||
|
|
||||||
type _lessThanResult int
|
type lessThanResult int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
lessThanFalse _lessThanResult = iota
|
lessThanFalse lessThanResult = iota
|
||||||
lessThanTrue
|
lessThanTrue
|
||||||
lessThanUndefined
|
lessThanUndefined
|
||||||
)
|
)
|
||||||
|
|
||||||
func calculateLessThan(left Value, right Value, leftFirst bool) _lessThanResult {
|
func calculateLessThan(left Value, right Value, leftFirst bool) lessThanResult {
|
||||||
var x, y Value
|
var x, y Value
|
||||||
if leftFirst {
|
if leftFirst {
|
||||||
x = toNumberPrimitive(left)
|
x = toNumberPrimitive(left)
|
||||||
|
@ -175,46 +171,46 @@ func calculateLessThan(left Value, right Value, leftFirst bool) _lessThanResult
|
||||||
return lessThanFalse
|
return lessThanFalse
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME Probably a map is not the most efficient way to do this
|
// FIXME Probably a map is not the most efficient way to do this.
|
||||||
var lessThanTable [4](map[_lessThanResult]bool) = [4](map[_lessThanResult]bool){
|
var lessThanTable [4](map[lessThanResult]bool) = [4](map[lessThanResult]bool){
|
||||||
// <
|
// <
|
||||||
map[_lessThanResult]bool{
|
map[lessThanResult]bool{
|
||||||
lessThanFalse: false,
|
lessThanFalse: false,
|
||||||
lessThanTrue: true,
|
lessThanTrue: true,
|
||||||
lessThanUndefined: false,
|
lessThanUndefined: false,
|
||||||
},
|
},
|
||||||
|
|
||||||
// >
|
// >
|
||||||
map[_lessThanResult]bool{
|
map[lessThanResult]bool{
|
||||||
lessThanFalse: false,
|
lessThanFalse: false,
|
||||||
lessThanTrue: true,
|
lessThanTrue: true,
|
||||||
lessThanUndefined: false,
|
lessThanUndefined: false,
|
||||||
},
|
},
|
||||||
|
|
||||||
// <=
|
// <=
|
||||||
map[_lessThanResult]bool{
|
map[lessThanResult]bool{
|
||||||
lessThanFalse: true,
|
lessThanFalse: true,
|
||||||
lessThanTrue: false,
|
lessThanTrue: false,
|
||||||
lessThanUndefined: false,
|
lessThanUndefined: false,
|
||||||
},
|
},
|
||||||
|
|
||||||
// >=
|
// >=
|
||||||
map[_lessThanResult]bool{
|
map[lessThanResult]bool{
|
||||||
lessThanFalse: true,
|
lessThanFalse: true,
|
||||||
lessThanTrue: false,
|
lessThanTrue: false,
|
||||||
lessThanUndefined: false,
|
lessThanUndefined: false,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_runtime) calculateComparison(comparator token.Token, left Value, right Value) bool {
|
func (rt *runtime) calculateComparison(comparator token.Token, left Value, right Value) bool {
|
||||||
// FIXME Use strictEqualityComparison?
|
// FIXME Use strictEqualityComparison?
|
||||||
// TODO This might be redundant now (with regards to evaluateComparison)
|
// TODO This might be redundant now (with regards to evaluateComparison)
|
||||||
x := left.resolve()
|
x := left.resolve()
|
||||||
y := right.resolve()
|
y := right.resolve()
|
||||||
|
|
||||||
kindEqualKind := false
|
var kindEqualKind bool
|
||||||
|
var negate bool
|
||||||
result := true
|
result := true
|
||||||
negate := false
|
|
||||||
|
|
||||||
switch comparator {
|
switch comparator {
|
||||||
case token.LESS:
|
case token.LESS:
|
||||||
|
@ -238,27 +234,28 @@ func (self *_runtime) calculateComparison(comparator token.Token, left Value, ri
|
||||||
negate = true
|
negate = true
|
||||||
fallthrough
|
fallthrough
|
||||||
case token.EQUAL:
|
case token.EQUAL:
|
||||||
if x.kind == y.kind {
|
switch {
|
||||||
|
case x.kind == y.kind:
|
||||||
kindEqualKind = true
|
kindEqualKind = true
|
||||||
} else if x.kind <= valueNull && y.kind <= valueNull {
|
case x.kind <= valueNull && y.kind <= valueNull:
|
||||||
result = true
|
result = true
|
||||||
} else if x.kind <= valueNull || y.kind <= valueNull {
|
case x.kind <= valueNull || y.kind <= valueNull:
|
||||||
result = false
|
result = false
|
||||||
} else if x.kind <= valueString && y.kind <= valueString {
|
case x.kind <= valueString && y.kind <= valueString:
|
||||||
result = x.float64() == y.float64()
|
result = x.float64() == y.float64()
|
||||||
} else if x.kind == valueBoolean {
|
case x.kind == valueBoolean:
|
||||||
result = self.calculateComparison(token.EQUAL, toValue_float64(x.float64()), y)
|
result = rt.calculateComparison(token.EQUAL, float64Value(x.float64()), y)
|
||||||
} else if y.kind == valueBoolean {
|
case y.kind == valueBoolean:
|
||||||
result = self.calculateComparison(token.EQUAL, x, toValue_float64(y.float64()))
|
result = rt.calculateComparison(token.EQUAL, x, float64Value(y.float64()))
|
||||||
} else if x.kind == valueObject {
|
case x.kind == valueObject:
|
||||||
result = self.calculateComparison(token.EQUAL, toPrimitive(x), y)
|
result = rt.calculateComparison(token.EQUAL, toPrimitiveValue(x), y)
|
||||||
} else if y.kind == valueObject {
|
case y.kind == valueObject:
|
||||||
result = self.calculateComparison(token.EQUAL, x, toPrimitive(y))
|
result = rt.calculateComparison(token.EQUAL, x, toPrimitiveValue(y))
|
||||||
} else {
|
default:
|
||||||
panic(hereBeDragons("Unable to test for equality: %v ==? %v", x, y))
|
panic(fmt.Sprintf("unknown types for equal: %v ==? %v", x, y))
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
panic(fmt.Errorf("Unknown comparator %s", comparator.String()))
|
panic(fmt.Sprintf("unknown comparator %s", comparator.String()))
|
||||||
}
|
}
|
||||||
|
|
||||||
if kindEqualKind {
|
if kindEqualKind {
|
||||||
|
@ -278,7 +275,7 @@ func (self *_runtime) calculateComparison(comparator token.Token, left Value, ri
|
||||||
case valueBoolean:
|
case valueBoolean:
|
||||||
result = x.bool() == y.bool()
|
result = x.bool() == y.bool()
|
||||||
case valueObject:
|
case valueObject:
|
||||||
result = x._object() == y._object()
|
result = x.object() == y.object()
|
||||||
default:
|
default:
|
||||||
goto ERROR
|
goto ERROR
|
||||||
}
|
}
|
||||||
|
|
110
v1/vendor/github.com/robertkrimen/otto/file/README.markdown
generated
vendored
|
@ -1,110 +0,0 @@
|
||||||
# file
|
|
||||||
--
|
|
||||||
import "github.com/robertkrimen/otto/file"
|
|
||||||
|
|
||||||
Package file encapsulates the file abstractions used by the ast & parser.
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
#### type File
|
|
||||||
|
|
||||||
```go
|
|
||||||
type File struct {
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
#### func NewFile
|
|
||||||
|
|
||||||
```go
|
|
||||||
func NewFile(filename, src string, base int) *File
|
|
||||||
```
|
|
||||||
|
|
||||||
#### func (*File) Base
|
|
||||||
|
|
||||||
```go
|
|
||||||
func (fl *File) Base() int
|
|
||||||
```
|
|
||||||
|
|
||||||
#### func (*File) Name
|
|
||||||
|
|
||||||
```go
|
|
||||||
func (fl *File) Name() string
|
|
||||||
```
|
|
||||||
|
|
||||||
#### func (*File) Source
|
|
||||||
|
|
||||||
```go
|
|
||||||
func (fl *File) Source() string
|
|
||||||
```
|
|
||||||
|
|
||||||
#### type FileSet
|
|
||||||
|
|
||||||
```go
|
|
||||||
type FileSet struct {
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
A FileSet represents a set of source files.
|
|
||||||
|
|
||||||
#### func (*FileSet) AddFile
|
|
||||||
|
|
||||||
```go
|
|
||||||
func (self *FileSet) AddFile(filename, src string) int
|
|
||||||
```
|
|
||||||
AddFile adds a new file with the given filename and src.
|
|
||||||
|
|
||||||
This an internal method, but exported for cross-package use.
|
|
||||||
|
|
||||||
#### func (*FileSet) File
|
|
||||||
|
|
||||||
```go
|
|
||||||
func (self *FileSet) File(idx Idx) *File
|
|
||||||
```
|
|
||||||
|
|
||||||
#### func (*FileSet) Position
|
|
||||||
|
|
||||||
```go
|
|
||||||
func (self *FileSet) Position(idx Idx) *Position
|
|
||||||
```
|
|
||||||
Position converts an Idx in the FileSet into a Position.
|
|
||||||
|
|
||||||
#### type Idx
|
|
||||||
|
|
||||||
```go
|
|
||||||
type Idx int
|
|
||||||
```
|
|
||||||
|
|
||||||
Idx is a compact encoding of a source position within a file set. It can be
|
|
||||||
converted into a Position for a more convenient, but much larger,
|
|
||||||
representation.
|
|
||||||
|
|
||||||
#### type Position
|
|
||||||
|
|
||||||
```go
|
|
||||||
type Position struct {
|
|
||||||
Filename string // The filename where the error occurred, if any
|
|
||||||
Offset int // The src offset
|
|
||||||
Line int // The line number, starting at 1
|
|
||||||
Column int // The column number, starting at 1 (The character count)
|
|
||||||
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Position describes an arbitrary source position including the filename, line,
|
|
||||||
and column location.
|
|
||||||
|
|
||||||
#### func (*Position) String
|
|
||||||
|
|
||||||
```go
|
|
||||||
func (self *Position) String() string
|
|
||||||
```
|
|
||||||
String returns a string in one of several forms:
|
|
||||||
|
|
||||||
file:line:column A valid position with filename
|
|
||||||
line:column A valid position without filename
|
|
||||||
file An invalid position with filename
|
|
||||||
- An invalid position without filename
|
|
||||||
|
|
||||||
--
|
|
||||||
**godocdown** http://github.com/robertkrimen/godocdown
|
|
47
v1/vendor/github.com/robertkrimen/otto/file/file.go
generated
vendored
|
@ -20,13 +20,12 @@ type Position struct {
|
||||||
Offset int // The src offset
|
Offset int // The src offset
|
||||||
Line int // The line number, starting at 1
|
Line int // The line number, starting at 1
|
||||||
Column int // The column number, starting at 1 (The character count)
|
Column int // The column number, starting at 1 (The character count)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// A Position is valid if the line number is > 0.
|
// A Position is valid if the line number is > 0.
|
||||||
|
|
||||||
func (self *Position) isValid() bool {
|
func (p *Position) isValid() bool {
|
||||||
return self.Line > 0
|
return p.Line > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// String returns a string in one of several forms:
|
// String returns a string in one of several forms:
|
||||||
|
@ -35,13 +34,13 @@ func (self *Position) isValid() bool {
|
||||||
// line:column A valid position without filename
|
// line:column A valid position without filename
|
||||||
// file An invalid position with filename
|
// file An invalid position with filename
|
||||||
// - An invalid position without filename
|
// - An invalid position without filename
|
||||||
func (self *Position) String() string {
|
func (p *Position) String() string {
|
||||||
str := self.Filename
|
str := p.Filename
|
||||||
if self.isValid() {
|
if p.isValid() {
|
||||||
if str != "" {
|
if str != "" {
|
||||||
str += ":"
|
str += ":"
|
||||||
}
|
}
|
||||||
str += fmt.Sprintf("%d:%d", self.Line, self.Column)
|
str += fmt.Sprintf("%d:%d", p.Line, p.Column)
|
||||||
}
|
}
|
||||||
if str == "" {
|
if str == "" {
|
||||||
str = "-"
|
str = "-"
|
||||||
|
@ -49,10 +48,8 @@ func (self *Position) String() string {
|
||||||
return str
|
return str
|
||||||
}
|
}
|
||||||
|
|
||||||
// FileSet
|
|
||||||
|
|
||||||
// A FileSet represents a set of source files.
|
// A FileSet represents a set of source files.
|
||||||
type FileSet struct {
|
type FileSet struct { //nolint: golint
|
||||||
files []*File
|
files []*File
|
||||||
last *File
|
last *File
|
||||||
}
|
}
|
||||||
|
@ -60,27 +57,28 @@ type FileSet struct {
|
||||||
// AddFile adds a new file with the given filename and src.
|
// AddFile adds a new file with the given filename and src.
|
||||||
//
|
//
|
||||||
// This an internal method, but exported for cross-package use.
|
// This an internal method, but exported for cross-package use.
|
||||||
func (self *FileSet) AddFile(filename, src string) int {
|
func (fs *FileSet) AddFile(filename, src string) int {
|
||||||
base := self.nextBase()
|
base := fs.nextBase()
|
||||||
file := &File{
|
file := &File{
|
||||||
name: filename,
|
name: filename,
|
||||||
src: src,
|
src: src,
|
||||||
base: base,
|
base: base,
|
||||||
}
|
}
|
||||||
self.files = append(self.files, file)
|
fs.files = append(fs.files, file)
|
||||||
self.last = file
|
fs.last = file
|
||||||
return base
|
return base
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *FileSet) nextBase() int {
|
func (fs *FileSet) nextBase() int {
|
||||||
if self.last == nil {
|
if fs.last == nil {
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
return self.last.base + len(self.last.src) + 1
|
return fs.last.base + len(fs.last.src) + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *FileSet) File(idx Idx) *File {
|
// File returns the File at idx or nil if not found.
|
||||||
for _, file := range self.files {
|
func (fs *FileSet) File(idx Idx) *File {
|
||||||
|
for _, file := range fs.files {
|
||||||
if idx <= Idx(file.base+len(file.src)) {
|
if idx <= Idx(file.base+len(file.src)) {
|
||||||
return file
|
return file
|
||||||
}
|
}
|
||||||
|
@ -89,8 +87,8 @@ func (self *FileSet) File(idx Idx) *File {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Position converts an Idx in the FileSet into a Position.
|
// Position converts an Idx in the FileSet into a Position.
|
||||||
func (self *FileSet) Position(idx Idx) *Position {
|
func (fs *FileSet) Position(idx Idx) *Position {
|
||||||
for _, file := range self.files {
|
for _, file := range fs.files {
|
||||||
if idx <= Idx(file.base+len(file.src)) {
|
if idx <= Idx(file.base+len(file.src)) {
|
||||||
return file.Position(idx - Idx(file.base))
|
return file.Position(idx - Idx(file.base))
|
||||||
}
|
}
|
||||||
|
@ -99,6 +97,7 @@ func (self *FileSet) Position(idx Idx) *Position {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// File represents a file to parse.
|
||||||
type File struct {
|
type File struct {
|
||||||
name string
|
name string
|
||||||
src string
|
src string
|
||||||
|
@ -106,6 +105,7 @@ type File struct {
|
||||||
sm *sourcemap.Consumer
|
sm *sourcemap.Consumer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewFile returns a new file with the given filename, src and base.
|
||||||
func NewFile(filename, src string, base int) *File {
|
func NewFile(filename, src string, base int) *File {
|
||||||
return &File{
|
return &File{
|
||||||
name: filename,
|
name: filename,
|
||||||
|
@ -114,23 +114,28 @@ func NewFile(filename, src string, base int) *File {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithSourceMap sets the source map of fl.
|
||||||
func (fl *File) WithSourceMap(sm *sourcemap.Consumer) *File {
|
func (fl *File) WithSourceMap(sm *sourcemap.Consumer) *File {
|
||||||
fl.sm = sm
|
fl.sm = sm
|
||||||
return fl
|
return fl
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Name returns the name of fl.
|
||||||
func (fl *File) Name() string {
|
func (fl *File) Name() string {
|
||||||
return fl.name
|
return fl.name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Source returns the source of fl.
|
||||||
func (fl *File) Source() string {
|
func (fl *File) Source() string {
|
||||||
return fl.src
|
return fl.src
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Base returns the base of fl.
|
||||||
func (fl *File) Base() int {
|
func (fl *File) Base() int {
|
||||||
return fl.base
|
return fl.base
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Position returns the position at idx or nil if not valid.
|
||||||
func (fl *File) Position(idx Idx) *Position {
|
func (fl *File) Position(idx Idx) *Position {
|
||||||
position := &Position{}
|
position := &Position{}
|
||||||
|
|
||||||
|
|
4
v1/vendor/github.com/robertkrimen/otto/generate.go
generated
vendored
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
package otto
|
||||||
|
|
||||||
|
//go:generate go run ./tools/gen-jscore -output inline.go
|
||||||
|
//go:generate stringer -type=valueKind -trimprefix=value -output=value_kind.gen.go
|
195
v1/vendor/github.com/robertkrimen/otto/global.go
generated
vendored
|
@ -7,12 +7,12 @@ import (
|
||||||
|
|
||||||
var (
|
var (
|
||||||
prototypeValueObject = interface{}(nil)
|
prototypeValueObject = interface{}(nil)
|
||||||
prototypeValueFunction = _nativeFunctionObject{
|
prototypeValueFunction = nativeFunctionObject{
|
||||||
call: func(_ FunctionCall) Value {
|
call: func(_ FunctionCall) Value {
|
||||||
return Value{}
|
return Value{}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
prototypeValueString = _stringASCII("")
|
prototypeValueString = stringASCII("")
|
||||||
// TODO Make this just false?
|
// TODO Make this just false?
|
||||||
prototypeValueBoolean = Value{
|
prototypeValueBoolean = Value{
|
||||||
kind: valueBoolean,
|
kind: valueBoolean,
|
||||||
|
@ -22,7 +22,7 @@ var (
|
||||||
kind: valueNumber,
|
kind: valueNumber,
|
||||||
value: 0,
|
value: 0,
|
||||||
}
|
}
|
||||||
prototypeValueDate = _dateObject{
|
prototypeValueDate = dateObject{
|
||||||
epoch: 0,
|
epoch: 0,
|
||||||
isNaN: false,
|
isNaN: false,
|
||||||
time: time.Unix(0, 0).UTC(),
|
time: time.Unix(0, 0).UTC(),
|
||||||
|
@ -31,7 +31,7 @@ var (
|
||||||
value: 0,
|
value: 0,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
prototypeValueRegExp = _regExpObject{
|
prototypeValueRegExp = regExpObject{
|
||||||
regularExpression: nil,
|
regularExpression: nil,
|
||||||
global: false,
|
global: false,
|
||||||
ignoreCase: false,
|
ignoreCase: false,
|
||||||
|
@ -41,102 +41,101 @@ var (
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func newContext() *_runtime {
|
func newContext() *runtime {
|
||||||
self := &_runtime{}
|
rt := &runtime{}
|
||||||
|
|
||||||
self.globalStash = self.newObjectStash(nil, nil)
|
rt.globalStash = rt.newObjectStash(nil, nil)
|
||||||
self.globalObject = self.globalStash.object
|
rt.globalObject = rt.globalStash.object
|
||||||
|
|
||||||
_newContext(self)
|
rt.newContext()
|
||||||
|
|
||||||
self.eval = self.globalObject.property["eval"].value.(Value).value.(*_object)
|
rt.eval = rt.globalObject.property["eval"].value.(Value).value.(*object)
|
||||||
self.globalObject.prototype = self.global.ObjectPrototype
|
rt.globalObject.prototype = rt.global.ObjectPrototype
|
||||||
|
|
||||||
return self
|
return rt
|
||||||
}
|
}
|
||||||
|
|
||||||
func (runtime *_runtime) newBaseObject() *_object {
|
func (rt *runtime) newBaseObject() *object {
|
||||||
self := newObject(runtime, "")
|
return newObject(rt, "")
|
||||||
return self
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (runtime *_runtime) newClassObject(class string) *_object {
|
func (rt *runtime) newClassObject(class string) *object {
|
||||||
return newObject(runtime, class)
|
return newObject(rt, class)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (runtime *_runtime) newPrimitiveObject(class string, value Value) *_object {
|
func (rt *runtime) newPrimitiveObject(class string, value Value) *object {
|
||||||
self := runtime.newClassObject(class)
|
o := rt.newClassObject(class)
|
||||||
self.value = value
|
o.value = value
|
||||||
return self
|
return o
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_object) primitiveValue() Value {
|
func (o *object) primitiveValue() Value {
|
||||||
switch value := self.value.(type) {
|
switch value := o.value.(type) {
|
||||||
case Value:
|
case Value:
|
||||||
return value
|
return value
|
||||||
case _stringObject:
|
case stringObjecter:
|
||||||
return toValue_string(value.String())
|
return stringValue(value.String())
|
||||||
}
|
}
|
||||||
return Value{}
|
return Value{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_object) hasPrimitive() bool {
|
func (o *object) hasPrimitive() bool { //nolint: unused
|
||||||
switch self.value.(type) {
|
switch o.value.(type) {
|
||||||
case Value, _stringObject:
|
case Value, stringObjecter:
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (runtime *_runtime) newObject() *_object {
|
func (rt *runtime) newObject() *object {
|
||||||
self := runtime.newClassObject(classObject)
|
o := rt.newClassObject(classObjectName)
|
||||||
self.prototype = runtime.global.ObjectPrototype
|
o.prototype = rt.global.ObjectPrototype
|
||||||
return self
|
return o
|
||||||
}
|
}
|
||||||
|
|
||||||
func (runtime *_runtime) newArray(length uint32) *_object {
|
func (rt *runtime) newArray(length uint32) *object {
|
||||||
self := runtime.newArrayObject(length)
|
o := rt.newArrayObject(length)
|
||||||
self.prototype = runtime.global.ArrayPrototype
|
o.prototype = rt.global.ArrayPrototype
|
||||||
return self
|
return o
|
||||||
}
|
}
|
||||||
|
|
||||||
func (runtime *_runtime) newArrayOf(valueArray []Value) *_object {
|
func (rt *runtime) newArrayOf(valueArray []Value) *object {
|
||||||
self := runtime.newArray(uint32(len(valueArray)))
|
o := rt.newArray(uint32(len(valueArray)))
|
||||||
for index, value := range valueArray {
|
for index, value := range valueArray {
|
||||||
if value.isEmpty() {
|
if value.isEmpty() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
self.defineProperty(strconv.FormatInt(int64(index), 10), value, 0111, false)
|
o.defineProperty(strconv.FormatInt(int64(index), 10), value, 0o111, false)
|
||||||
}
|
}
|
||||||
return self
|
return o
|
||||||
}
|
}
|
||||||
|
|
||||||
func (runtime *_runtime) newString(value Value) *_object {
|
func (rt *runtime) newString(value Value) *object {
|
||||||
self := runtime.newStringObject(value)
|
o := rt.newStringObject(value)
|
||||||
self.prototype = runtime.global.StringPrototype
|
o.prototype = rt.global.StringPrototype
|
||||||
return self
|
return o
|
||||||
}
|
}
|
||||||
|
|
||||||
func (runtime *_runtime) newBoolean(value Value) *_object {
|
func (rt *runtime) newBoolean(value Value) *object {
|
||||||
self := runtime.newBooleanObject(value)
|
o := rt.newBooleanObject(value)
|
||||||
self.prototype = runtime.global.BooleanPrototype
|
o.prototype = rt.global.BooleanPrototype
|
||||||
return self
|
return o
|
||||||
}
|
}
|
||||||
|
|
||||||
func (runtime *_runtime) newNumber(value Value) *_object {
|
func (rt *runtime) newNumber(value Value) *object {
|
||||||
self := runtime.newNumberObject(value)
|
o := rt.newNumberObject(value)
|
||||||
self.prototype = runtime.global.NumberPrototype
|
o.prototype = rt.global.NumberPrototype
|
||||||
return self
|
return o
|
||||||
}
|
}
|
||||||
|
|
||||||
func (runtime *_runtime) newRegExp(patternValue Value, flagsValue Value) *_object {
|
func (rt *runtime) newRegExp(patternValue Value, flagsValue Value) *object {
|
||||||
pattern := ""
|
pattern := ""
|
||||||
flags := ""
|
flags := ""
|
||||||
if object := patternValue._object(); object != nil && object.class == classRegExp {
|
if obj := patternValue.object(); obj != nil && obj.class == classRegExpName {
|
||||||
if flagsValue.IsDefined() {
|
if flagsValue.IsDefined() {
|
||||||
panic(runtime.panicTypeError("Cannot supply flags when constructing one RegExp from another"))
|
panic(rt.panicTypeError("Cannot supply flags when constructing one RegExp from another"))
|
||||||
}
|
}
|
||||||
regExp := object.regExpValue()
|
regExp := obj.regExpValue()
|
||||||
pattern = regExp.source
|
pattern = regExp.source
|
||||||
flags = regExp.flags
|
flags = regExp.flags
|
||||||
} else {
|
} else {
|
||||||
|
@ -148,71 +147,71 @@ func (runtime *_runtime) newRegExp(patternValue Value, flagsValue Value) *_objec
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return runtime._newRegExp(pattern, flags)
|
return rt.newRegExpDirect(pattern, flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (runtime *_runtime) _newRegExp(pattern string, flags string) *_object {
|
func (rt *runtime) newRegExpDirect(pattern string, flags string) *object {
|
||||||
self := runtime.newRegExpObject(pattern, flags)
|
o := rt.newRegExpObject(pattern, flags)
|
||||||
self.prototype = runtime.global.RegExpPrototype
|
o.prototype = rt.global.RegExpPrototype
|
||||||
return self
|
return o
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Should (probably) be one argument, right? This is redundant
|
// TODO Should (probably) be one argument, right? This is redundant.
|
||||||
func (runtime *_runtime) newDate(epoch float64) *_object {
|
func (rt *runtime) newDate(epoch float64) *object {
|
||||||
self := runtime.newDateObject(epoch)
|
o := rt.newDateObject(epoch)
|
||||||
self.prototype = runtime.global.DatePrototype
|
o.prototype = rt.global.DatePrototype
|
||||||
return self
|
return o
|
||||||
}
|
}
|
||||||
|
|
||||||
func (runtime *_runtime) newError(name string, message Value, stackFramesToPop int) *_object {
|
func (rt *runtime) newError(name string, message Value, stackFramesToPop int) *object {
|
||||||
switch name {
|
switch name {
|
||||||
case "EvalError":
|
case "EvalError":
|
||||||
return runtime.newEvalError(message)
|
return rt.newEvalError(message)
|
||||||
case "TypeError":
|
case "TypeError":
|
||||||
return runtime.newTypeError(message)
|
return rt.newTypeError(message)
|
||||||
case "RangeError":
|
case "RangeError":
|
||||||
return runtime.newRangeError(message)
|
return rt.newRangeError(message)
|
||||||
case "ReferenceError":
|
case "ReferenceError":
|
||||||
return runtime.newReferenceError(message)
|
return rt.newReferenceError(message)
|
||||||
case "SyntaxError":
|
case "SyntaxError":
|
||||||
return runtime.newSyntaxError(message)
|
return rt.newSyntaxError(message)
|
||||||
case "URIError":
|
case "URIError":
|
||||||
return runtime.newURIError(message)
|
return rt.newURIError(message)
|
||||||
}
|
}
|
||||||
|
|
||||||
self := runtime.newErrorObject(name, message, stackFramesToPop)
|
obj := rt.newErrorObject(name, message, stackFramesToPop)
|
||||||
self.prototype = runtime.global.ErrorPrototype
|
obj.prototype = rt.global.ErrorPrototype
|
||||||
if name != "" {
|
if name != "" {
|
||||||
self.defineProperty("name", toValue_string(name), 0111, false)
|
obj.defineProperty("name", stringValue(name), 0o111, false)
|
||||||
}
|
}
|
||||||
return self
|
return obj
|
||||||
}
|
}
|
||||||
|
|
||||||
func (runtime *_runtime) newNativeFunction(name, file string, line int, _nativeFunction _nativeFunction) *_object {
|
func (rt *runtime) newNativeFunction(name, file string, line int, fn nativeFunction) *object {
|
||||||
self := runtime.newNativeFunctionObject(name, file, line, _nativeFunction, 0)
|
o := rt.newNativeFunctionObject(name, file, line, fn, 0)
|
||||||
self.prototype = runtime.global.FunctionPrototype
|
o.prototype = rt.global.FunctionPrototype
|
||||||
prototype := runtime.newObject()
|
prototype := rt.newObject()
|
||||||
self.defineProperty("prototype", toValue_object(prototype), 0100, false)
|
o.defineProperty("prototype", objectValue(prototype), 0o100, false)
|
||||||
prototype.defineProperty("constructor", toValue_object(self), 0100, false)
|
prototype.defineProperty("constructor", objectValue(o), 0o100, false)
|
||||||
return self
|
return o
|
||||||
}
|
}
|
||||||
|
|
||||||
func (runtime *_runtime) newNodeFunction(node *_nodeFunctionLiteral, scopeEnvironment _stash) *_object {
|
func (rt *runtime) newNodeFunction(node *nodeFunctionLiteral, scopeEnvironment stasher) *object {
|
||||||
// TODO Implement 13.2 fully
|
// TODO Implement 13.2 fully
|
||||||
self := runtime.newNodeFunctionObject(node, scopeEnvironment)
|
o := rt.newNodeFunctionObject(node, scopeEnvironment)
|
||||||
self.prototype = runtime.global.FunctionPrototype
|
o.prototype = rt.global.FunctionPrototype
|
||||||
prototype := runtime.newObject()
|
prototype := rt.newObject()
|
||||||
self.defineProperty("prototype", toValue_object(prototype), 0100, false)
|
o.defineProperty("prototype", objectValue(prototype), 0o100, false)
|
||||||
prototype.defineProperty("constructor", toValue_object(self), 0101, false)
|
prototype.defineProperty("constructor", objectValue(o), 0o101, false)
|
||||||
return self
|
return o
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME Only in one place...
|
// FIXME Only in one place...
|
||||||
func (runtime *_runtime) newBoundFunction(target *_object, this Value, argumentList []Value) *_object {
|
func (rt *runtime) newBoundFunction(target *object, this Value, argumentList []Value) *object {
|
||||||
self := runtime.newBoundFunctionObject(target, this, argumentList)
|
o := rt.newBoundFunctionObject(target, this, argumentList)
|
||||||
self.prototype = runtime.global.FunctionPrototype
|
o.prototype = rt.global.FunctionPrototype
|
||||||
prototype := runtime.newObject()
|
prototype := rt.newObject()
|
||||||
self.defineProperty("prototype", toValue_object(prototype), 0100, false)
|
o.defineProperty("prototype", objectValue(prototype), 0o100, false)
|
||||||
prototype.defineProperty("constructor", toValue_object(self), 0100, false)
|
prototype.defineProperty("constructor", objectValue(o), 0o100, false)
|
||||||
return self
|
return o
|
||||||
}
|
}
|
||||||
|
|
11782
v1/vendor/github.com/robertkrimen/otto/inline.go
generated
vendored
1087
v1/vendor/github.com/robertkrimen/otto/inline.pl
generated
vendored
4
v1/vendor/github.com/robertkrimen/otto/locale.go
generated
vendored
|
@ -2,6 +2,4 @@ package otto
|
||||||
|
|
||||||
import "golang.org/x/text/language"
|
import "golang.org/x/text/language"
|
||||||
|
|
||||||
var (
|
var defaultLanguage = language.MustParse("en-US")
|
||||||
defaultLanguage = language.MustParse("en-US")
|
|
||||||
)
|
|
||||||
|
|
141
v1/vendor/github.com/robertkrimen/otto/object.go
generated
vendored
|
@ -1,78 +1,78 @@
|
||||||
package otto
|
package otto
|
||||||
|
|
||||||
type _object struct {
|
type object struct {
|
||||||
runtime *_runtime
|
runtime *runtime
|
||||||
|
|
||||||
class string
|
class string
|
||||||
objectClass *_objectClass
|
objectClass *objectClass
|
||||||
value interface{}
|
value interface{}
|
||||||
|
|
||||||
prototype *_object
|
prototype *object
|
||||||
extensible bool
|
extensible bool
|
||||||
|
|
||||||
property map[string]_property
|
property map[string]property
|
||||||
propertyOrder []string
|
propertyOrder []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func newObject(runtime *_runtime, class string) *_object {
|
func newObject(rt *runtime, class string) *object {
|
||||||
self := &_object{
|
o := &object{
|
||||||
runtime: runtime,
|
runtime: rt,
|
||||||
class: class,
|
class: class,
|
||||||
objectClass: _classObject,
|
objectClass: classObject,
|
||||||
property: make(map[string]_property),
|
property: make(map[string]property),
|
||||||
extensible: true,
|
extensible: true,
|
||||||
}
|
}
|
||||||
return self
|
return o
|
||||||
}
|
}
|
||||||
|
|
||||||
// 8.12
|
// 8.12
|
||||||
|
|
||||||
// 8.12.1
|
// 8.12.1.
|
||||||
func (self *_object) getOwnProperty(name string) *_property {
|
func (o *object) getOwnProperty(name string) *property {
|
||||||
return self.objectClass.getOwnProperty(self, name)
|
return o.objectClass.getOwnProperty(o, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 8.12.2
|
// 8.12.2.
|
||||||
func (self *_object) getProperty(name string) *_property {
|
func (o *object) getProperty(name string) *property {
|
||||||
return self.objectClass.getProperty(self, name)
|
return o.objectClass.getProperty(o, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 8.12.3
|
// 8.12.3.
|
||||||
func (self *_object) get(name string) Value {
|
func (o *object) get(name string) Value {
|
||||||
return self.objectClass.get(self, name)
|
return o.objectClass.get(o, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 8.12.4
|
// 8.12.4.
|
||||||
func (self *_object) canPut(name string) bool {
|
func (o *object) canPut(name string) bool {
|
||||||
return self.objectClass.canPut(self, name)
|
return o.objectClass.canPut(o, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 8.12.5
|
// 8.12.5.
|
||||||
func (self *_object) put(name string, value Value, throw bool) {
|
func (o *object) put(name string, value Value, throw bool) {
|
||||||
self.objectClass.put(self, name, value, throw)
|
o.objectClass.put(o, name, value, throw)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 8.12.6
|
// 8.12.6.
|
||||||
func (self *_object) hasProperty(name string) bool {
|
func (o *object) hasProperty(name string) bool {
|
||||||
return self.objectClass.hasProperty(self, name)
|
return o.objectClass.hasProperty(o, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_object) hasOwnProperty(name string) bool {
|
func (o *object) hasOwnProperty(name string) bool {
|
||||||
return self.objectClass.hasOwnProperty(self, name)
|
return o.objectClass.hasOwnProperty(o, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
type _defaultValueHint int
|
type defaultValueHint int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
defaultValueNoHint _defaultValueHint = iota
|
defaultValueNoHint defaultValueHint = iota
|
||||||
defaultValueHintString
|
defaultValueHintString
|
||||||
defaultValueHintNumber
|
defaultValueHintNumber
|
||||||
)
|
)
|
||||||
|
|
||||||
// 8.12.8
|
// 8.12.8.
|
||||||
func (self *_object) DefaultValue(hint _defaultValueHint) Value {
|
func (o *object) DefaultValue(hint defaultValueHint) Value {
|
||||||
if hint == defaultValueNoHint {
|
if hint == defaultValueNoHint {
|
||||||
if self.class == classDate {
|
if o.class == classDateName {
|
||||||
// Date exception
|
// Date exception
|
||||||
hint = defaultValueHintString
|
hint = defaultValueHintString
|
||||||
} else {
|
} else {
|
||||||
|
@ -84,72 +84,67 @@ func (self *_object) DefaultValue(hint _defaultValueHint) Value {
|
||||||
methodSequence = []string{"toString", "valueOf"}
|
methodSequence = []string{"toString", "valueOf"}
|
||||||
}
|
}
|
||||||
for _, methodName := range methodSequence {
|
for _, methodName := range methodSequence {
|
||||||
method := self.get(methodName)
|
method := o.get(methodName)
|
||||||
// FIXME This is redundant...
|
// FIXME This is redundant...
|
||||||
if method.isCallable() {
|
if method.isCallable() {
|
||||||
result := method._object().call(toValue_object(self), nil, false, nativeFrame)
|
result := method.object().call(objectValue(o), nil, false, nativeFrame)
|
||||||
if result.IsPrimitive() {
|
if result.IsPrimitive() {
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
panic(self.runtime.panicTypeError())
|
panic(o.runtime.panicTypeError("Object.DefaultValue unknown"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_object) String() string {
|
func (o *object) String() string {
|
||||||
return self.DefaultValue(defaultValueHintString).string()
|
return o.DefaultValue(defaultValueHintString).string()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_object) defineProperty(name string, value Value, mode _propertyMode, throw bool) bool {
|
func (o *object) defineProperty(name string, value Value, mode propertyMode, throw bool) bool { //nolint: unparam
|
||||||
return self.defineOwnProperty(name, _property{value, mode}, throw)
|
return o.defineOwnProperty(name, property{value, mode}, throw)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 8.12.9
|
// 8.12.9.
|
||||||
func (self *_object) defineOwnProperty(name string, descriptor _property, throw bool) bool {
|
func (o *object) defineOwnProperty(name string, descriptor property, throw bool) bool {
|
||||||
return self.objectClass.defineOwnProperty(self, name, descriptor, throw)
|
return o.objectClass.defineOwnProperty(o, name, descriptor, throw)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_object) delete(name string, throw bool) bool {
|
func (o *object) delete(name string, throw bool) bool {
|
||||||
return self.objectClass.delete(self, name, throw)
|
return o.objectClass.delete(o, name, throw)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_object) enumerate(all bool, each func(string) bool) {
|
func (o *object) enumerate(all bool, each func(string) bool) {
|
||||||
self.objectClass.enumerate(self, all, each)
|
o.objectClass.enumerate(o, all, each)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_object) _exists(name string) bool {
|
func (o *object) readProperty(name string) (property, bool) {
|
||||||
_, exists := self.property[name]
|
prop, exists := o.property[name]
|
||||||
return exists
|
return prop, exists
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_object) _read(name string) (_property, bool) {
|
func (o *object) writeProperty(name string, value interface{}, mode propertyMode) {
|
||||||
property, exists := self.property[name]
|
|
||||||
return property, exists
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *_object) _write(name string, value interface{}, mode _propertyMode) {
|
|
||||||
if value == nil {
|
if value == nil {
|
||||||
value = Value{}
|
value = Value{}
|
||||||
}
|
}
|
||||||
_, exists := self.property[name]
|
if _, exists := o.property[name]; !exists {
|
||||||
self.property[name] = _property{value, mode}
|
o.propertyOrder = append(o.propertyOrder, name)
|
||||||
if !exists {
|
|
||||||
self.propertyOrder = append(self.propertyOrder, name)
|
|
||||||
}
|
}
|
||||||
|
o.property[name] = property{value, mode}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_object) _delete(name string) {
|
func (o *object) deleteProperty(name string) {
|
||||||
_, exists := self.property[name]
|
if _, exists := o.property[name]; !exists {
|
||||||
delete(self.property, name)
|
return
|
||||||
if exists {
|
}
|
||||||
for index, property := range self.propertyOrder {
|
|
||||||
if name == property {
|
delete(o.property, name)
|
||||||
if index == len(self.propertyOrder)-1 {
|
for index, prop := range o.propertyOrder {
|
||||||
self.propertyOrder = self.propertyOrder[:index]
|
if name == prop {
|
||||||
|
if index == len(o.propertyOrder)-1 {
|
||||||
|
o.propertyOrder = o.propertyOrder[:index]
|
||||||
} else {
|
} else {
|
||||||
self.propertyOrder = append(self.propertyOrder[:index], self.propertyOrder[index+1:]...)
|
o.propertyOrder = append(o.propertyOrder[:index], o.propertyOrder[index+1:]...)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
358
v1/vendor/github.com/robertkrimen/otto/object_class.go
generated
vendored
|
@ -4,24 +4,24 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
)
|
)
|
||||||
|
|
||||||
type _objectClass struct {
|
type objectClass struct {
|
||||||
getOwnProperty func(*_object, string) *_property
|
getOwnProperty func(*object, string) *property
|
||||||
getProperty func(*_object, string) *_property
|
getProperty func(*object, string) *property
|
||||||
get func(*_object, string) Value
|
get func(*object, string) Value
|
||||||
canPut func(*_object, string) bool
|
canPut func(*object, string) bool
|
||||||
put func(*_object, string, Value, bool)
|
put func(*object, string, Value, bool)
|
||||||
hasProperty func(*_object, string) bool
|
hasProperty func(*object, string) bool
|
||||||
hasOwnProperty func(*_object, string) bool
|
hasOwnProperty func(*object, string) bool
|
||||||
defineOwnProperty func(*_object, string, _property, bool) bool
|
defineOwnProperty func(*object, string, property, bool) bool
|
||||||
delete func(*_object, string, bool) bool
|
delete func(*object, string, bool) bool
|
||||||
enumerate func(*_object, bool, func(string) bool)
|
enumerate func(*object, bool, func(string) bool)
|
||||||
clone func(*_object, *_object, *_clone) *_object
|
clone func(*object, *object, *cloner) *object
|
||||||
marshalJSON func(*_object) json.Marshaler
|
marshalJSON func(*object) json.Marshaler
|
||||||
}
|
}
|
||||||
|
|
||||||
func objectEnumerate(self *_object, all bool, each func(string) bool) {
|
func objectEnumerate(obj *object, all bool, each func(string) bool) {
|
||||||
for _, name := range self.propertyOrder {
|
for _, name := range obj.propertyOrder {
|
||||||
if all || self.property[name].enumerable() {
|
if all || obj.property[name].enumerable() {
|
||||||
if !each(name) {
|
if !each(name) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -29,20 +29,17 @@ func objectEnumerate(self *_object, all bool, each func(string) bool) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var classObject,
|
||||||
_classObject,
|
classArray,
|
||||||
_classArray,
|
classString,
|
||||||
_classString,
|
classArguments,
|
||||||
_classArguments,
|
classGoStruct,
|
||||||
_classGoStruct,
|
classGoMap,
|
||||||
_classGoMap,
|
classGoArray,
|
||||||
_classGoArray,
|
classGoSlice *objectClass
|
||||||
_classGoSlice,
|
|
||||||
_ *_objectClass
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
_classObject = &_objectClass{
|
classObject = &objectClass{
|
||||||
objectGetOwnProperty,
|
objectGetOwnProperty,
|
||||||
objectGetProperty,
|
objectGetProperty,
|
||||||
objectGet,
|
objectGet,
|
||||||
|
@ -57,7 +54,7 @@ func init() {
|
||||||
nil,
|
nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
_classArray = &_objectClass{
|
classArray = &objectClass{
|
||||||
objectGetOwnProperty,
|
objectGetOwnProperty,
|
||||||
objectGetProperty,
|
objectGetProperty,
|
||||||
objectGet,
|
objectGet,
|
||||||
|
@ -72,7 +69,7 @@ func init() {
|
||||||
nil,
|
nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
_classString = &_objectClass{
|
classString = &objectClass{
|
||||||
stringGetOwnProperty,
|
stringGetOwnProperty,
|
||||||
objectGetProperty,
|
objectGetProperty,
|
||||||
objectGet,
|
objectGet,
|
||||||
|
@ -87,7 +84,7 @@ func init() {
|
||||||
nil,
|
nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
_classArguments = &_objectClass{
|
classArguments = &objectClass{
|
||||||
argumentsGetOwnProperty,
|
argumentsGetOwnProperty,
|
||||||
objectGetProperty,
|
objectGetProperty,
|
||||||
argumentsGet,
|
argumentsGet,
|
||||||
|
@ -102,7 +99,7 @@ func init() {
|
||||||
nil,
|
nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
_classGoStruct = &_objectClass{
|
classGoStruct = &objectClass{
|
||||||
goStructGetOwnProperty,
|
goStructGetOwnProperty,
|
||||||
objectGetProperty,
|
objectGetProperty,
|
||||||
objectGet,
|
objectGet,
|
||||||
|
@ -117,7 +114,7 @@ func init() {
|
||||||
goStructMarshalJSON,
|
goStructMarshalJSON,
|
||||||
}
|
}
|
||||||
|
|
||||||
_classGoMap = &_objectClass{
|
classGoMap = &objectClass{
|
||||||
goMapGetOwnProperty,
|
goMapGetOwnProperty,
|
||||||
objectGetProperty,
|
objectGetProperty,
|
||||||
objectGet,
|
objectGet,
|
||||||
|
@ -132,7 +129,7 @@ func init() {
|
||||||
nil,
|
nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
_classGoArray = &_objectClass{
|
classGoArray = &objectClass{
|
||||||
goArrayGetOwnProperty,
|
goArrayGetOwnProperty,
|
||||||
objectGetProperty,
|
objectGetProperty,
|
||||||
objectGet,
|
objectGet,
|
||||||
|
@ -147,7 +144,7 @@ func init() {
|
||||||
nil,
|
nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
_classGoSlice = &_objectClass{
|
classGoSlice = &objectClass{
|
||||||
goSliceGetOwnProperty,
|
goSliceGetOwnProperty,
|
||||||
objectGetProperty,
|
objectGetProperty,
|
||||||
objectGet,
|
objectGet,
|
||||||
|
@ -165,85 +162,81 @@ func init() {
|
||||||
|
|
||||||
// Allons-y
|
// Allons-y
|
||||||
|
|
||||||
// 8.12.1
|
// 8.12.1.
|
||||||
func objectGetOwnProperty(self *_object, name string) *_property {
|
func objectGetOwnProperty(obj *object, name string) *property {
|
||||||
// Return a _copy_ of the property
|
// Return a _copy_ of the prop
|
||||||
property, exists := self._read(name)
|
prop, exists := obj.readProperty(name)
|
||||||
if !exists {
|
if !exists {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return &property
|
return &prop
|
||||||
}
|
}
|
||||||
|
|
||||||
// 8.12.2
|
// 8.12.2.
|
||||||
func objectGetProperty(self *_object, name string) *_property {
|
func objectGetProperty(obj *object, name string) *property {
|
||||||
property := self.getOwnProperty(name)
|
prop := obj.getOwnProperty(name)
|
||||||
if property != nil {
|
if prop != nil {
|
||||||
return property
|
return prop
|
||||||
}
|
}
|
||||||
if self.prototype != nil {
|
if obj.prototype != nil {
|
||||||
return self.prototype.getProperty(name)
|
return obj.prototype.getProperty(name)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 8.12.3
|
// 8.12.3.
|
||||||
func objectGet(self *_object, name string) Value {
|
func objectGet(obj *object, name string) Value {
|
||||||
property := self.getProperty(name)
|
if prop := obj.getProperty(name); prop != nil {
|
||||||
if property != nil {
|
return prop.get(obj)
|
||||||
return property.get(self)
|
|
||||||
}
|
}
|
||||||
return Value{}
|
return Value{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 8.12.4
|
// 8.12.4.
|
||||||
func objectCanPut(self *_object, name string) bool {
|
func objectCanPut(obj *object, name string) bool {
|
||||||
canPut, _, _ := _objectCanPut(self, name)
|
canPut, _, _ := objectCanPutDetails(obj, name)
|
||||||
return canPut
|
return canPut
|
||||||
}
|
}
|
||||||
|
|
||||||
func _objectCanPut(self *_object, name string) (canPut bool, property *_property, setter *_object) {
|
func objectCanPutDetails(obj *object, name string) (canPut bool, prop *property, setter *object) { //nolint: nonamedreturns
|
||||||
property = self.getOwnProperty(name)
|
prop = obj.getOwnProperty(name)
|
||||||
if property != nil {
|
if prop != nil {
|
||||||
switch propertyValue := property.value.(type) {
|
switch propertyValue := prop.value.(type) {
|
||||||
case Value:
|
case Value:
|
||||||
canPut = property.writable()
|
return prop.writable(), prop, nil
|
||||||
return
|
case propertyGetSet:
|
||||||
case _propertyGetSet:
|
|
||||||
setter = propertyValue[1]
|
setter = propertyValue[1]
|
||||||
canPut = setter != nil
|
return setter != nil, prop, setter
|
||||||
return
|
|
||||||
default:
|
default:
|
||||||
panic(self.runtime.panicTypeError())
|
panic(obj.runtime.panicTypeError("unexpected type %T to Object.CanPutDetails", prop.value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.prototype == nil {
|
if obj.prototype == nil {
|
||||||
return self.extensible, nil, nil
|
return obj.extensible, nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
property = self.prototype.getProperty(name)
|
prop = obj.prototype.getProperty(name)
|
||||||
if property == nil {
|
if prop == nil {
|
||||||
return self.extensible, nil, nil
|
return obj.extensible, nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
switch propertyValue := property.value.(type) {
|
switch propertyValue := prop.value.(type) {
|
||||||
case Value:
|
case Value:
|
||||||
if !self.extensible {
|
if !obj.extensible {
|
||||||
return false, nil, nil
|
return false, nil, nil
|
||||||
}
|
}
|
||||||
return property.writable(), nil, nil
|
return prop.writable(), nil, nil
|
||||||
case _propertyGetSet:
|
case propertyGetSet:
|
||||||
setter = propertyValue[1]
|
setter = propertyValue[1]
|
||||||
canPut = setter != nil
|
return setter != nil, prop, setter
|
||||||
return
|
|
||||||
default:
|
default:
|
||||||
panic(self.runtime.panicTypeError())
|
panic(obj.runtime.panicTypeError("unexpected type %T to Object.CanPutDetails", prop.value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 8.12.5
|
// 8.12.5.
|
||||||
func objectPut(self *_object, name string, value Value, throw bool) {
|
func objectPut(obj *object, name string, value Value, throw bool) {
|
||||||
if true {
|
if true {
|
||||||
// Shortcut...
|
// Shortcut...
|
||||||
//
|
//
|
||||||
|
@ -253,16 +246,17 @@ func objectPut(self *_object, name string, value Value, throw bool) {
|
||||||
// If that were to no longer be the case, we would have to have
|
// If that were to no longer be the case, we would have to have
|
||||||
// something to detect that here, so that we do not use an
|
// something to detect that here, so that we do not use an
|
||||||
// incompatible canPut routine
|
// incompatible canPut routine
|
||||||
canPut, property, setter := _objectCanPut(self, name)
|
canPut, prop, setter := objectCanPutDetails(obj, name)
|
||||||
if !canPut {
|
switch {
|
||||||
self.runtime.typeErrorResult(throw)
|
case !canPut:
|
||||||
} else if setter != nil {
|
obj.runtime.typeErrorResult(throw)
|
||||||
setter.call(toValue(self), []Value{value}, false, nativeFrame)
|
case setter != nil:
|
||||||
} else if property != nil {
|
setter.call(toValue(obj), []Value{value}, false, nativeFrame)
|
||||||
property.value = value
|
case prop != nil:
|
||||||
self.defineOwnProperty(name, *property, throw)
|
prop.value = value
|
||||||
} else {
|
obj.defineOwnProperty(name, *prop, throw)
|
||||||
self.defineProperty(name, value, 0111, throw)
|
default:
|
||||||
|
obj.defineProperty(name, value, 0o111, throw)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -270,69 +264,77 @@ func objectPut(self *_object, name string, value Value, throw bool) {
|
||||||
// The long way...
|
// The long way...
|
||||||
//
|
//
|
||||||
// Right now, code should never get here, see above
|
// Right now, code should never get here, see above
|
||||||
if !self.canPut(name) {
|
if !obj.canPut(name) {
|
||||||
self.runtime.typeErrorResult(throw)
|
obj.runtime.typeErrorResult(throw)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
property := self.getOwnProperty(name)
|
prop := obj.getOwnProperty(name)
|
||||||
if property == nil {
|
if prop == nil {
|
||||||
property = self.getProperty(name)
|
prop = obj.getProperty(name)
|
||||||
if property != nil {
|
if prop != nil {
|
||||||
if getSet, isAccessor := property.value.(_propertyGetSet); isAccessor {
|
if getSet, isAccessor := prop.value.(propertyGetSet); isAccessor {
|
||||||
getSet[1].call(toValue(self), []Value{value}, false, nativeFrame)
|
getSet[1].call(toValue(obj), []Value{value}, false, nativeFrame)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.defineProperty(name, value, 0111, throw)
|
obj.defineProperty(name, value, 0o111, throw)
|
||||||
} else {
|
return
|
||||||
switch propertyValue := property.value.(type) {
|
}
|
||||||
|
|
||||||
|
switch propertyValue := prop.value.(type) {
|
||||||
case Value:
|
case Value:
|
||||||
property.value = value
|
prop.value = value
|
||||||
self.defineOwnProperty(name, *property, throw)
|
obj.defineOwnProperty(name, *prop, throw)
|
||||||
case _propertyGetSet:
|
case propertyGetSet:
|
||||||
if propertyValue[1] != nil {
|
if propertyValue[1] != nil {
|
||||||
propertyValue[1].call(toValue(self), []Value{value}, false, nativeFrame)
|
propertyValue[1].call(toValue(obj), []Value{value}, false, nativeFrame)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if throw {
|
if throw {
|
||||||
panic(self.runtime.panicTypeError())
|
panic(obj.runtime.panicTypeError("Object.Put nil second parameter to propertyGetSet"))
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
panic(self.runtime.panicTypeError())
|
panic(obj.runtime.panicTypeError("Object.Put unexpected type %T", prop.value))
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 8.12.6
|
// 8.12.6.
|
||||||
func objectHasProperty(self *_object, name string) bool {
|
func objectHasProperty(obj *object, name string) bool {
|
||||||
return self.getProperty(name) != nil
|
return obj.getProperty(name) != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func objectHasOwnProperty(self *_object, name string) bool {
|
func objectHasOwnProperty(obj *object, name string) bool {
|
||||||
return self.getOwnProperty(name) != nil
|
return obj.getOwnProperty(name) != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 8.12.9
|
// 8.12.9.
|
||||||
func objectDefineOwnProperty(self *_object, name string, descriptor _property, throw bool) bool {
|
func objectDefineOwnProperty(obj *object, name string, descriptor property, throw bool) bool {
|
||||||
property, exists := self._read(name)
|
reject := func(reason string) bool {
|
||||||
{
|
if throw {
|
||||||
|
panic(obj.runtime.panicTypeError("Object.DefineOwnProperty: %s", reason))
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
prop, exists := obj.readProperty(name)
|
||||||
if !exists {
|
if !exists {
|
||||||
if !self.extensible {
|
if !obj.extensible {
|
||||||
goto Reject
|
return reject("not exists and not extensible")
|
||||||
}
|
}
|
||||||
if newGetSet, isAccessor := descriptor.value.(_propertyGetSet); isAccessor {
|
if newGetSet, isAccessor := descriptor.value.(propertyGetSet); isAccessor {
|
||||||
if newGetSet[0] == &_nilGetSetObject {
|
if newGetSet[0] == &nilGetSetObject {
|
||||||
newGetSet[0] = nil
|
newGetSet[0] = nil
|
||||||
}
|
}
|
||||||
if newGetSet[1] == &_nilGetSetObject {
|
if newGetSet[1] == &nilGetSetObject {
|
||||||
newGetSet[1] = nil
|
newGetSet[1] = nil
|
||||||
}
|
}
|
||||||
descriptor.value = newGetSet
|
descriptor.value = newGetSet
|
||||||
}
|
}
|
||||||
self._write(name, descriptor.value, descriptor.mode)
|
obj.writeProperty(name, descriptor.value, descriptor.mode)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
if descriptor.isEmpty() {
|
if descriptor.isEmpty() {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -340,43 +342,45 @@ func objectDefineOwnProperty(self *_object, name string, descriptor _property, t
|
||||||
// TODO Per 8.12.9.6 - We should shortcut here (returning true) if
|
// TODO Per 8.12.9.6 - We should shortcut here (returning true) if
|
||||||
// the current and new (define) properties are the same
|
// the current and new (define) properties are the same
|
||||||
|
|
||||||
configurable := property.configurable()
|
configurable := prop.configurable()
|
||||||
if !configurable {
|
if !configurable {
|
||||||
if descriptor.configurable() {
|
if descriptor.configurable() {
|
||||||
goto Reject
|
return reject("property and descriptor not configurable")
|
||||||
}
|
}
|
||||||
// Test that, if enumerable is set on the property descriptor, then it should
|
// Test that, if enumerable is set on the property descriptor, then it should
|
||||||
// be the same as the existing property
|
// be the same as the existing property
|
||||||
if descriptor.enumerateSet() && descriptor.enumerable() != property.enumerable() {
|
if descriptor.enumerateSet() && descriptor.enumerable() != prop.enumerable() {
|
||||||
goto Reject
|
return reject("property not configurable and enumerable miss match")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
value, isDataDescriptor := property.value.(Value)
|
|
||||||
getSet, _ := property.value.(_propertyGetSet)
|
value, isDataDescriptor := prop.value.(Value)
|
||||||
if descriptor.isGenericDescriptor() {
|
getSet, _ := prop.value.(propertyGetSet)
|
||||||
|
switch {
|
||||||
|
case descriptor.isGenericDescriptor():
|
||||||
// GenericDescriptor
|
// GenericDescriptor
|
||||||
} else if isDataDescriptor != descriptor.isDataDescriptor() {
|
case isDataDescriptor != descriptor.isDataDescriptor():
|
||||||
// DataDescriptor <=> AccessorDescriptor
|
// DataDescriptor <=> AccessorDescriptor
|
||||||
if !configurable {
|
if !configurable {
|
||||||
goto Reject
|
return reject("property descriptor not configurable")
|
||||||
}
|
}
|
||||||
} else if isDataDescriptor && descriptor.isDataDescriptor() {
|
case isDataDescriptor && descriptor.isDataDescriptor():
|
||||||
// DataDescriptor <=> DataDescriptor
|
// DataDescriptor <=> DataDescriptor
|
||||||
if !configurable {
|
if !configurable {
|
||||||
if !property.writable() && descriptor.writable() {
|
if !prop.writable() && descriptor.writable() {
|
||||||
goto Reject
|
return reject("property not configurable or writeable and descriptor not writeable")
|
||||||
}
|
}
|
||||||
if !property.writable() {
|
if !prop.writable() {
|
||||||
if descriptor.value != nil && !sameValue(value, descriptor.value.(Value)) {
|
if descriptor.value != nil && !sameValue(value, descriptor.value.(Value)) {
|
||||||
goto Reject
|
return reject("property not configurable or writeable and descriptor not the same")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
default:
|
||||||
// AccessorDescriptor <=> AccessorDescriptor
|
// AccessorDescriptor <=> AccessorDescriptor
|
||||||
newGetSet, _ := descriptor.value.(_propertyGetSet)
|
newGetSet, _ := descriptor.value.(propertyGetSet)
|
||||||
presentGet, presentSet := true, true
|
presentGet, presentSet := true, true
|
||||||
if newGetSet[0] == &_nilGetSetObject {
|
if newGetSet[0] == &nilGetSetObject {
|
||||||
// Present, but nil
|
// Present, but nil
|
||||||
newGetSet[0] = nil
|
newGetSet[0] = nil
|
||||||
} else if newGetSet[0] == nil {
|
} else if newGetSet[0] == nil {
|
||||||
|
@ -384,7 +388,7 @@ func objectDefineOwnProperty(self *_object, name string, descriptor _property, t
|
||||||
newGetSet[0] = getSet[0]
|
newGetSet[0] = getSet[0]
|
||||||
presentGet = false
|
presentGet = false
|
||||||
}
|
}
|
||||||
if newGetSet[1] == &_nilGetSetObject {
|
if newGetSet[1] == &nilGetSetObject {
|
||||||
// Present, but nil
|
// Present, but nil
|
||||||
newGetSet[1] = nil
|
newGetSet[1] = nil
|
||||||
} else if newGetSet[1] == nil {
|
} else if newGetSet[1] == nil {
|
||||||
|
@ -394,97 +398,91 @@ func objectDefineOwnProperty(self *_object, name string, descriptor _property, t
|
||||||
}
|
}
|
||||||
if !configurable {
|
if !configurable {
|
||||||
if (presentGet && (getSet[0] != newGetSet[0])) || (presentSet && (getSet[1] != newGetSet[1])) {
|
if (presentGet && (getSet[0] != newGetSet[0])) || (presentSet && (getSet[1] != newGetSet[1])) {
|
||||||
goto Reject
|
return reject("access descriptor not configurable")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
descriptor.value = newGetSet
|
descriptor.value = newGetSet
|
||||||
}
|
}
|
||||||
{
|
|
||||||
// This section will preserve attributes of
|
// This section will preserve attributes of
|
||||||
// the original property, if necessary
|
// the original property, if necessary
|
||||||
value1 := descriptor.value
|
value1 := descriptor.value
|
||||||
if value1 == nil {
|
if value1 == nil {
|
||||||
value1 = property.value
|
value1 = prop.value
|
||||||
} else if newGetSet, isAccessor := descriptor.value.(_propertyGetSet); isAccessor {
|
} else if newGetSet, isAccessor := descriptor.value.(propertyGetSet); isAccessor {
|
||||||
if newGetSet[0] == &_nilGetSetObject {
|
if newGetSet[0] == &nilGetSetObject {
|
||||||
newGetSet[0] = nil
|
newGetSet[0] = nil
|
||||||
}
|
}
|
||||||
if newGetSet[1] == &_nilGetSetObject {
|
if newGetSet[1] == &nilGetSetObject {
|
||||||
newGetSet[1] = nil
|
newGetSet[1] = nil
|
||||||
}
|
}
|
||||||
value1 = newGetSet
|
value1 = newGetSet
|
||||||
}
|
}
|
||||||
mode1 := descriptor.mode
|
mode1 := descriptor.mode
|
||||||
if mode1&0222 != 0 {
|
if mode1&0o222 != 0 {
|
||||||
// TODO Factor this out into somewhere testable
|
// TODO Factor this out into somewhere testable
|
||||||
// (Maybe put into switch ...)
|
// (Maybe put into switch ...)
|
||||||
mode0 := property.mode
|
mode0 := prop.mode
|
||||||
if mode1&0200 != 0 {
|
if mode1&0o200 != 0 {
|
||||||
if descriptor.isDataDescriptor() {
|
if descriptor.isDataDescriptor() {
|
||||||
mode1 &= ^0200 // Turn off "writable" missing
|
mode1 &= ^0o200 // Turn off "writable" missing
|
||||||
mode1 |= (mode0 & 0100)
|
mode1 |= (mode0 & 0o100)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if mode1&020 != 0 {
|
if mode1&0o20 != 0 {
|
||||||
mode1 |= (mode0 & 010)
|
mode1 |= (mode0 & 0o10)
|
||||||
}
|
}
|
||||||
if mode1&02 != 0 {
|
if mode1&0o2 != 0 {
|
||||||
mode1 |= (mode0 & 01)
|
mode1 |= (mode0 & 0o1)
|
||||||
}
|
}
|
||||||
mode1 &= 0311 // 0311 to preserve the non-setting on "writable"
|
mode1 &= 0o311 // 0311 to preserve the non-setting on "writable"
|
||||||
}
|
|
||||||
self._write(name, value1, mode1)
|
|
||||||
}
|
}
|
||||||
|
obj.writeProperty(name, value1, mode1)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
Reject:
|
|
||||||
if throw {
|
|
||||||
panic(self.runtime.panicTypeError())
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func objectDelete(self *_object, name string, throw bool) bool {
|
func objectDelete(obj *object, name string, throw bool) bool {
|
||||||
property_ := self.getOwnProperty(name)
|
prop := obj.getOwnProperty(name)
|
||||||
if property_ == nil {
|
if prop == nil {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if property_.configurable() {
|
if prop.configurable() {
|
||||||
self._delete(name)
|
obj.deleteProperty(name)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return self.runtime.typeErrorResult(throw)
|
return obj.runtime.typeErrorResult(throw)
|
||||||
}
|
}
|
||||||
|
|
||||||
func objectClone(in *_object, out *_object, clone *_clone) *_object {
|
func objectClone(in *object, out *object, clone *cloner) *object {
|
||||||
*out = *in
|
*out = *in
|
||||||
|
|
||||||
out.runtime = clone.runtime
|
out.runtime = clone.runtime
|
||||||
if out.prototype != nil {
|
if out.prototype != nil {
|
||||||
out.prototype = clone.object(in.prototype)
|
out.prototype = clone.object(in.prototype)
|
||||||
}
|
}
|
||||||
out.property = make(map[string]_property, len(in.property))
|
out.property = make(map[string]property, len(in.property))
|
||||||
out.propertyOrder = make([]string, len(in.propertyOrder))
|
out.propertyOrder = make([]string, len(in.propertyOrder))
|
||||||
copy(out.propertyOrder, in.propertyOrder)
|
copy(out.propertyOrder, in.propertyOrder)
|
||||||
for index, property := range in.property {
|
for index, prop := range in.property {
|
||||||
out.property[index] = clone.property(property)
|
out.property[index] = clone.property(prop)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch value := in.value.(type) {
|
switch value := in.value.(type) {
|
||||||
case _nativeFunctionObject:
|
case nativeFunctionObject:
|
||||||
out.value = value
|
out.value = value
|
||||||
case _bindFunctionObject:
|
case bindFunctionObject:
|
||||||
out.value = _bindFunctionObject{
|
out.value = bindFunctionObject{
|
||||||
target: clone.object(value.target),
|
target: clone.object(value.target),
|
||||||
this: clone.value(value.this),
|
this: clone.value(value.this),
|
||||||
argumentList: clone.valueArray(value.argumentList),
|
argumentList: clone.valueArray(value.argumentList),
|
||||||
}
|
}
|
||||||
case _nodeFunctionObject:
|
case nodeFunctionObject:
|
||||||
out.value = _nodeFunctionObject{
|
out.value = nodeFunctionObject{
|
||||||
node: value.node,
|
node: value.node,
|
||||||
stash: clone.stash(value.stash),
|
stash: clone.stash(value.stash),
|
||||||
}
|
}
|
||||||
case _argumentsObject:
|
case argumentsObject:
|
||||||
out.value = value.clone(clone)
|
out.value = value.clone(clone)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
280
v1/vendor/github.com/robertkrimen/otto/otto.go
generated
vendored
|
@ -39,10 +39,8 @@ Set a string
|
||||||
Get the value of an expression
|
Get the value of an expression
|
||||||
|
|
||||||
value, _ = vm.Run("xyzzy.length")
|
value, _ = vm.Run("xyzzy.length")
|
||||||
{
|
// iv is an int64 with a value of 16
|
||||||
// value is an int64 with a value of 16
|
iv, _ := value.ToInteger()
|
||||||
value, _ := value.ToInteger()
|
|
||||||
}
|
|
||||||
|
|
||||||
An error happens
|
An error happens
|
||||||
|
|
||||||
|
@ -216,9 +214,7 @@ http://github.com/robertkrimen/natto
|
||||||
Here is some more discussion of the issue:
|
Here is some more discussion of the issue:
|
||||||
|
|
||||||
* http://book.mixu.net/node/ch2.html
|
* http://book.mixu.net/node/ch2.html
|
||||||
|
|
||||||
* http://en.wikipedia.org/wiki/Reentrancy_%28computing%29
|
* http://en.wikipedia.org/wiki/Reentrancy_%28computing%29
|
||||||
|
|
||||||
* http://aaroncrane.co.uk/2009/02/perl_safe_signals/
|
* http://aaroncrane.co.uk/2009/02/perl_safe_signals/
|
||||||
*/
|
*/
|
||||||
package otto
|
package otto
|
||||||
|
@ -232,36 +228,41 @@ import (
|
||||||
"github.com/robertkrimen/otto/registry"
|
"github.com/robertkrimen/otto/registry"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Otto is the representation of the JavaScript runtime. Each instance of Otto has a self-contained namespace.
|
// Otto is the representation of the JavaScript runtime.
|
||||||
|
// Each instance of Otto has a self-contained namespace.
|
||||||
type Otto struct {
|
type Otto struct {
|
||||||
// Interrupt is a channel for interrupting the runtime. You can use this to halt a long running execution, for example.
|
// Interrupt is a channel for interrupting the runtime. You can use this to halt a long running execution, for example.
|
||||||
// See "Halting Problem" for more information.
|
// See "Halting Problem" for more information.
|
||||||
Interrupt chan func()
|
Interrupt chan func()
|
||||||
runtime *_runtime
|
runtime *runtime
|
||||||
}
|
}
|
||||||
|
|
||||||
// New will allocate a new JavaScript runtime
|
// New will allocate a new JavaScript runtime.
|
||||||
func New() *Otto {
|
func New() *Otto {
|
||||||
self := &Otto{
|
o := &Otto{
|
||||||
runtime: newContext(),
|
runtime: newContext(),
|
||||||
}
|
}
|
||||||
self.runtime.otto = self
|
o.runtime.otto = o
|
||||||
self.runtime.traceLimit = 10
|
o.runtime.traceLimit = 10
|
||||||
self.Set("console", self.runtime.newConsole())
|
if err := o.Set("console", o.runtime.newConsole()); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
registry.Apply(func(entry registry.Entry) {
|
registry.Apply(func(entry registry.Entry) {
|
||||||
self.Run(entry.Source())
|
if _, err := o.Run(entry.Source()); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
return self
|
return o
|
||||||
}
|
}
|
||||||
|
|
||||||
func (otto *Otto) clone() *Otto {
|
func (o *Otto) clone() *Otto {
|
||||||
self := &Otto{
|
n := &Otto{
|
||||||
runtime: otto.runtime.clone(),
|
runtime: o.runtime.clone(),
|
||||||
}
|
}
|
||||||
self.runtime.otto = self
|
n.runtime.otto = n
|
||||||
return self
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run will allocate a new JavaScript runtime, run the given source
|
// Run will allocate a new JavaScript runtime, run the given source
|
||||||
|
@ -289,8 +290,8 @@ func Run(src interface{}) (*Otto, Value, error) {
|
||||||
// src may also be a Script.
|
// src may also be a Script.
|
||||||
//
|
//
|
||||||
// src may also be a Program, but if the AST has been modified, then runtime behavior is undefined.
|
// src may also be a Program, but if the AST has been modified, then runtime behavior is undefined.
|
||||||
func (self Otto) Run(src interface{}) (Value, error) {
|
func (o Otto) Run(src interface{}) (Value, error) {
|
||||||
value, err := self.runtime.cmpl_run(src, nil)
|
value, err := o.runtime.cmplRun(src, nil)
|
||||||
if !value.safe() {
|
if !value.safe() {
|
||||||
value = Value{}
|
value = Value{}
|
||||||
}
|
}
|
||||||
|
@ -302,13 +303,13 @@ func (self Otto) Run(src interface{}) (Value, error) {
|
||||||
// By staying in the same scope, the code evaluated has access to everything
|
// By staying in the same scope, the code evaluated has access to everything
|
||||||
// already defined in the current stack frame. This is most useful in, for
|
// already defined in the current stack frame. This is most useful in, for
|
||||||
// example, a debugger call.
|
// example, a debugger call.
|
||||||
func (self Otto) Eval(src interface{}) (Value, error) {
|
func (o Otto) Eval(src interface{}) (Value, error) {
|
||||||
if self.runtime.scope == nil {
|
if o.runtime.scope == nil {
|
||||||
self.runtime.enterGlobalScope()
|
o.runtime.enterGlobalScope()
|
||||||
defer self.runtime.leaveScope()
|
defer o.runtime.leaveScope()
|
||||||
}
|
}
|
||||||
|
|
||||||
value, err := self.runtime.cmpl_eval(src, nil)
|
value, err := o.runtime.cmplEval(src, nil)
|
||||||
if !value.safe() {
|
if !value.safe() {
|
||||||
value = Value{}
|
value = Value{}
|
||||||
}
|
}
|
||||||
|
@ -319,10 +320,10 @@ func (self Otto) Eval(src interface{}) (Value, error) {
|
||||||
//
|
//
|
||||||
// If there is an error (like the binding does not exist), then the value
|
// If there is an error (like the binding does not exist), then the value
|
||||||
// will be undefined.
|
// will be undefined.
|
||||||
func (self Otto) Get(name string) (Value, error) {
|
func (o Otto) Get(name string) (Value, error) {
|
||||||
value := Value{}
|
value := Value{}
|
||||||
err := catchPanic(func() {
|
err := catchPanic(func() {
|
||||||
value = self.getValue(name)
|
value = o.getValue(name)
|
||||||
})
|
})
|
||||||
if !value.safe() {
|
if !value.safe() {
|
||||||
value = Value{}
|
value = Value{}
|
||||||
|
@ -330,8 +331,8 @@ func (self Otto) Get(name string) (Value, error) {
|
||||||
return value, err
|
return value, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self Otto) getValue(name string) Value {
|
func (o Otto) getValue(name string) Value {
|
||||||
return self.runtime.globalStash.getBinding(name, false)
|
return o.runtime.globalStash.getBinding(name, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the top-level binding of the given name to the given value.
|
// Set the top-level binding of the given name to the given value.
|
||||||
|
@ -343,29 +344,29 @@ func (self Otto) getValue(name string) Value {
|
||||||
// fails), then an error is returned.
|
// fails), then an error is returned.
|
||||||
//
|
//
|
||||||
// If the top-level binding does not exist, it will be created.
|
// If the top-level binding does not exist, it will be created.
|
||||||
func (self Otto) Set(name string, value interface{}) error {
|
func (o Otto) Set(name string, value interface{}) error {
|
||||||
{
|
val, err := o.ToValue(value)
|
||||||
value, err := self.ToValue(value)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = catchPanic(func() {
|
|
||||||
self.setValue(name, value)
|
return catchPanic(func() {
|
||||||
|
o.setValue(name, val)
|
||||||
})
|
})
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self Otto) setValue(name string, value Value) {
|
func (o Otto) setValue(name string, value Value) {
|
||||||
self.runtime.globalStash.setValue(name, value, false)
|
o.runtime.globalStash.setValue(name, value, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self Otto) SetDebuggerHandler(fn func(vm *Otto)) {
|
// SetDebuggerHandler sets the debugger handler to fn.
|
||||||
self.runtime.debugger = fn
|
func (o Otto) SetDebuggerHandler(fn func(vm *Otto)) {
|
||||||
|
o.runtime.debugger = fn
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self Otto) SetRandomSource(fn func() float64) {
|
// SetRandomSource sets the random source to fn.
|
||||||
self.runtime.random = fn
|
func (o Otto) SetRandomSource(fn func() float64) {
|
||||||
|
o.runtime.random = fn
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetStackDepthLimit sets an upper limit to the depth of the JavaScript
|
// SetStackDepthLimit sets an upper limit to the depth of the JavaScript
|
||||||
|
@ -376,41 +377,41 @@ func (self Otto) SetRandomSource(fn func() float64) {
|
||||||
// JavaScript makes a call to a Go function, otto won't keep track of what
|
// JavaScript makes a call to a Go function, otto won't keep track of what
|
||||||
// happens outside the interpreter. So if your Go function is infinitely
|
// happens outside the interpreter. So if your Go function is infinitely
|
||||||
// recursive, you're still in trouble.
|
// recursive, you're still in trouble.
|
||||||
func (self Otto) SetStackDepthLimit(limit int) {
|
func (o Otto) SetStackDepthLimit(limit int) {
|
||||||
self.runtime.stackLimit = limit
|
o.runtime.stackLimit = limit
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetStackTraceLimit sets an upper limit to the number of stack frames that
|
// SetStackTraceLimit sets an upper limit to the number of stack frames that
|
||||||
// otto will use when formatting an error's stack trace. By default, the limit
|
// otto will use when formatting an error's stack trace. By default, the limit
|
||||||
// is 10. This is consistent with V8 and SpiderMonkey.
|
// is 10. This is consistent with V8 and SpiderMonkey.
|
||||||
//
|
//
|
||||||
// TODO: expose via `Error.stackTraceLimit`
|
// TODO: expose via `Error.stackTraceLimit`.
|
||||||
func (self Otto) SetStackTraceLimit(limit int) {
|
func (o Otto) SetStackTraceLimit(limit int) {
|
||||||
self.runtime.traceLimit = limit
|
o.runtime.traceLimit = limit
|
||||||
}
|
}
|
||||||
|
|
||||||
// MakeCustomError creates a new Error object with the given name and message,
|
// MakeCustomError creates a new Error object with the given name and message,
|
||||||
// returning it as a Value.
|
// returning it as a Value.
|
||||||
func (self Otto) MakeCustomError(name, message string) Value {
|
func (o Otto) MakeCustomError(name, message string) Value {
|
||||||
return self.runtime.toValue(self.runtime.newError(name, self.runtime.toValue(message), 0))
|
return o.runtime.toValue(o.runtime.newError(name, o.runtime.toValue(message), 0))
|
||||||
}
|
}
|
||||||
|
|
||||||
// MakeRangeError creates a new RangeError object with the given message,
|
// MakeRangeError creates a new RangeError object with the given message,
|
||||||
// returning it as a Value.
|
// returning it as a Value.
|
||||||
func (self Otto) MakeRangeError(message string) Value {
|
func (o Otto) MakeRangeError(message string) Value {
|
||||||
return self.runtime.toValue(self.runtime.newRangeError(self.runtime.toValue(message)))
|
return o.runtime.toValue(o.runtime.newRangeError(o.runtime.toValue(message)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// MakeSyntaxError creates a new SyntaxError object with the given message,
|
// MakeSyntaxError creates a new SyntaxError object with the given message,
|
||||||
// returning it as a Value.
|
// returning it as a Value.
|
||||||
func (self Otto) MakeSyntaxError(message string) Value {
|
func (o Otto) MakeSyntaxError(message string) Value {
|
||||||
return self.runtime.toValue(self.runtime.newSyntaxError(self.runtime.toValue(message)))
|
return o.runtime.toValue(o.runtime.newSyntaxError(o.runtime.toValue(message)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// MakeTypeError creates a new TypeError object with the given message,
|
// MakeTypeError creates a new TypeError object with the given message,
|
||||||
// returning it as a Value.
|
// returning it as a Value.
|
||||||
func (self Otto) MakeTypeError(message string) Value {
|
func (o Otto) MakeTypeError(message string) Value {
|
||||||
return self.runtime.toValue(self.runtime.newTypeError(self.runtime.toValue(message)))
|
return o.runtime.toValue(o.runtime.newTypeError(o.runtime.toValue(message)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Context is a structure that contains information about the current execution
|
// Context is a structure that contains information about the current execution
|
||||||
|
@ -427,48 +428,49 @@ type Context struct {
|
||||||
|
|
||||||
// Context returns the current execution context of the vm, traversing up to
|
// Context returns the current execution context of the vm, traversing up to
|
||||||
// ten stack frames, and skipping any innermost native function stack frames.
|
// ten stack frames, and skipping any innermost native function stack frames.
|
||||||
func (self Otto) Context() Context {
|
func (o Otto) Context() Context {
|
||||||
return self.ContextSkip(10, true)
|
return o.ContextSkip(10, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ContextLimit returns the current execution context of the vm, with a
|
// ContextLimit returns the current execution context of the vm, with a
|
||||||
// specific limit on the number of stack frames to traverse, skipping any
|
// specific limit on the number of stack frames to traverse, skipping any
|
||||||
// innermost native function stack frames.
|
// innermost native function stack frames.
|
||||||
func (self Otto) ContextLimit(limit int) Context {
|
func (o Otto) ContextLimit(limit int) Context {
|
||||||
return self.ContextSkip(limit, true)
|
return o.ContextSkip(limit, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ContextSkip returns the current execution context of the vm, with a
|
// ContextSkip returns the current execution context of the vm, with a
|
||||||
// specific limit on the number of stack frames to traverse, optionally
|
// specific limit on the number of stack frames to traverse, optionally
|
||||||
// skipping any innermost native function stack frames.
|
// skipping any innermost native function stack frames.
|
||||||
func (self Otto) ContextSkip(limit int, skipNative bool) (ctx Context) {
|
func (o Otto) ContextSkip(limit int, skipNative bool) Context {
|
||||||
// Ensure we are operating in a scope
|
// Ensure we are operating in a scope
|
||||||
if self.runtime.scope == nil {
|
if o.runtime.scope == nil {
|
||||||
self.runtime.enterGlobalScope()
|
o.runtime.enterGlobalScope()
|
||||||
defer self.runtime.leaveScope()
|
defer o.runtime.leaveScope()
|
||||||
}
|
}
|
||||||
|
|
||||||
scope := self.runtime.scope
|
curScope := o.runtime.scope
|
||||||
frame := scope.frame
|
frm := curScope.frame
|
||||||
|
|
||||||
for skipNative && frame.native && scope.outer != nil {
|
for skipNative && frm.native && curScope.outer != nil {
|
||||||
scope = scope.outer
|
curScope = curScope.outer
|
||||||
frame = scope.frame
|
frm = curScope.frame
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get location information
|
// Get location information
|
||||||
|
var ctx Context
|
||||||
ctx.Filename = "<unknown>"
|
ctx.Filename = "<unknown>"
|
||||||
ctx.Callee = frame.callee
|
ctx.Callee = frm.callee
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case frame.native:
|
case frm.native:
|
||||||
ctx.Filename = frame.nativeFile
|
ctx.Filename = frm.nativeFile
|
||||||
ctx.Line = frame.nativeLine
|
ctx.Line = frm.nativeLine
|
||||||
ctx.Column = 0
|
ctx.Column = 0
|
||||||
case frame.file != nil:
|
case frm.file != nil:
|
||||||
ctx.Filename = "<anonymous>"
|
ctx.Filename = "<anonymous>"
|
||||||
|
|
||||||
if p := frame.file.Position(file.Idx(frame.offset)); p != nil {
|
if p := frm.file.Position(file.Idx(frm.offset)); p != nil {
|
||||||
ctx.Line = p.Line
|
ctx.Line = p.Line
|
||||||
ctx.Column = p.Column
|
ctx.Column = p.Column
|
||||||
|
|
||||||
|
@ -479,14 +481,14 @@ func (self Otto) ContextSkip(limit int, skipNative bool) (ctx Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the current scope this Value
|
// Get the current scope this Value
|
||||||
ctx.This = toValue_object(scope.this)
|
ctx.This = objectValue(curScope.this)
|
||||||
|
|
||||||
// Build stacktrace (up to 10 levels deep)
|
// Build stacktrace (up to 10 levels deep)
|
||||||
ctx.Symbols = make(map[string]Value)
|
ctx.Symbols = make(map[string]Value)
|
||||||
ctx.Stacktrace = append(ctx.Stacktrace, frame.location())
|
ctx.Stacktrace = append(ctx.Stacktrace, frm.location())
|
||||||
for limit != 0 {
|
for limit != 0 {
|
||||||
// Get variables
|
// Get variables
|
||||||
stash := scope.lexical
|
stash := curScope.lexical
|
||||||
for {
|
for {
|
||||||
for _, name := range getStashProperties(stash) {
|
for _, name := range getStashProperties(stash) {
|
||||||
if _, ok := ctx.Symbols[name]; !ok {
|
if _, ok := ctx.Symbols[name]; !ok {
|
||||||
|
@ -499,17 +501,17 @@ func (self Otto) ContextSkip(limit int, skipNative bool) (ctx Context) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
scope = scope.outer
|
curScope = curScope.outer
|
||||||
if scope == nil {
|
if curScope == nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if scope.frame.offset >= 0 {
|
if curScope.frame.offset >= 0 {
|
||||||
ctx.Stacktrace = append(ctx.Stacktrace, scope.frame.location())
|
ctx.Stacktrace = append(ctx.Stacktrace, curScope.frame.location())
|
||||||
}
|
}
|
||||||
limit--
|
limit--
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return ctx
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call the given JavaScript with a given this and arguments.
|
// Call the given JavaScript with a given this and arguments.
|
||||||
|
@ -531,7 +533,7 @@ func (self Otto) ContextSkip(limit int, skipNative bool) (ctx Context) {
|
||||||
// // This will perform a concat on the given array and return the result
|
// // This will perform a concat on the given array and return the result
|
||||||
// // value is [ 1, 2, 3, undefined, 4, 5, 6, 7, "abc" ]
|
// // value is [ 1, 2, 3, undefined, 4, 5, 6, 7, "abc" ]
|
||||||
// value, _ := vm.Call(`[ 1, 2, 3, undefined, 4 ].concat`, nil, 5, 6, 7, "abc")
|
// value, _ := vm.Call(`[ 1, 2, 3, undefined, 4 ].concat`, nil, 5, 6, 7, "abc")
|
||||||
func (self Otto) Call(source string, this interface{}, argumentList ...interface{}) (Value, error) {
|
func (o Otto) Call(source string, this interface{}, argumentList ...interface{}) (Value, error) {
|
||||||
thisValue := Value{}
|
thisValue := Value{}
|
||||||
|
|
||||||
construct := false
|
construct := false
|
||||||
|
@ -541,19 +543,19 @@ func (self Otto) Call(source string, this interface{}, argumentList ...interface
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME enterGlobalScope
|
// FIXME enterGlobalScope
|
||||||
self.runtime.enterGlobalScope()
|
o.runtime.enterGlobalScope()
|
||||||
defer func() {
|
defer func() {
|
||||||
self.runtime.leaveScope()
|
o.runtime.leaveScope()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if !construct && this == nil {
|
if !construct && this == nil {
|
||||||
program, err := self.runtime.cmpl_parse("", source+"()", nil)
|
program, err := o.runtime.cmplParse("", source+"()", nil)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
if node, ok := program.body[0].(*_nodeExpressionStatement); ok {
|
if node, ok := program.body[0].(*nodeExpressionStatement); ok {
|
||||||
if node, ok := node.expression.(*_nodeCallExpression); ok {
|
if node, ok := node.expression.(*nodeCallExpression); ok {
|
||||||
var value Value
|
var value Value
|
||||||
err := catchPanic(func() {
|
err := catchPanic(func() {
|
||||||
value = self.runtime.cmpl_evaluate_nodeCallExpression(node, argumentList)
|
value = o.runtime.cmplEvaluateNodeCallExpression(node, argumentList)
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Value{}, err
|
return Value{}, err
|
||||||
|
@ -563,36 +565,33 @@ func (self Otto) Call(source string, this interface{}, argumentList ...interface
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
value, err := self.ToValue(this)
|
value, err := o.ToValue(this)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Value{}, err
|
return Value{}, err
|
||||||
}
|
}
|
||||||
thisValue = value
|
thisValue = value
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
val := thisValue
|
||||||
this := thisValue
|
fn, err := o.Run(source)
|
||||||
|
|
||||||
fn, err := self.Run(source)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Value{}, err
|
return Value{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if construct {
|
if construct {
|
||||||
result, err := fn.constructSafe(self.runtime, this, argumentList...)
|
result, err := fn.constructSafe(o.runtime, val, argumentList...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Value{}, err
|
return Value{}, err
|
||||||
}
|
}
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
result, err := fn.Call(this, argumentList...)
|
result, err := fn.Call(val, argumentList...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Value{}, err
|
return Value{}, err
|
||||||
}
|
}
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Object will run the given source and return the result as an object.
|
// Object will run the given source and return the result as an object.
|
||||||
//
|
//
|
||||||
|
@ -611,8 +610,8 @@ func (self Otto) Call(source string, this interface{}, argumentList ...interface
|
||||||
//
|
//
|
||||||
// If there is an error (like the source does not result in an object), then
|
// If there is an error (like the source does not result in an object), then
|
||||||
// nil and an error is returned.
|
// nil and an error is returned.
|
||||||
func (self Otto) Object(source string) (*Object, error) {
|
func (o Otto) Object(source string) (*Object, error) {
|
||||||
value, err := self.runtime.cmpl_run(source, nil)
|
value, err := o.runtime.cmplRun(source, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -623,8 +622,8 @@ func (self Otto) Object(source string) (*Object, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToValue will convert an interface{} value to a value digestible by otto/JavaScript.
|
// ToValue will convert an interface{} value to a value digestible by otto/JavaScript.
|
||||||
func (self Otto) ToValue(value interface{}) (Value, error) {
|
func (o Otto) ToValue(value interface{}) (Value, error) {
|
||||||
return self.runtime.safeToValue(value)
|
return o.runtime.safeToValue(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy will create a copy/clone of the runtime.
|
// Copy will create a copy/clone of the runtime.
|
||||||
|
@ -635,30 +634,20 @@ func (self Otto) ToValue(value interface{}) (Value, error) {
|
||||||
// etc. into a new runtime.
|
// etc. into a new runtime.
|
||||||
//
|
//
|
||||||
// Be on the lookout for memory leaks or inadvertent sharing of resources.
|
// Be on the lookout for memory leaks or inadvertent sharing of resources.
|
||||||
func (in *Otto) Copy() *Otto {
|
func (o *Otto) Copy() *Otto {
|
||||||
out := &Otto{
|
out := &Otto{
|
||||||
runtime: in.runtime.clone(),
|
runtime: o.runtime.clone(),
|
||||||
}
|
}
|
||||||
out.runtime.otto = out
|
out.runtime.otto = out
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
// Object{}
|
|
||||||
|
|
||||||
// Object is the representation of a JavaScript object.
|
// Object is the representation of a JavaScript object.
|
||||||
type Object struct {
|
type Object struct {
|
||||||
object *_object
|
object *object
|
||||||
value Value
|
value Value
|
||||||
}
|
}
|
||||||
|
|
||||||
func _newObject(object *_object, value Value) *Object {
|
|
||||||
// value MUST contain object!
|
|
||||||
return &Object{
|
|
||||||
object: object,
|
|
||||||
value: value,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Call a method on the object.
|
// Call a method on the object.
|
||||||
//
|
//
|
||||||
// It is essentially equivalent to:
|
// It is essentially equivalent to:
|
||||||
|
@ -671,27 +660,27 @@ func _newObject(object *_object, value Value) *Object {
|
||||||
// 1. There is an error during conversion of the argument list
|
// 1. There is an error during conversion of the argument list
|
||||||
// 2. The property is not actually a function
|
// 2. The property is not actually a function
|
||||||
// 3. An (uncaught) exception is thrown
|
// 3. An (uncaught) exception is thrown
|
||||||
func (self Object) Call(name string, argumentList ...interface{}) (Value, error) {
|
func (o Object) Call(name string, argumentList ...interface{}) (Value, error) {
|
||||||
// TODO: Insert an example using JavaScript below...
|
// TODO: Insert an example using JavaScript below...
|
||||||
// e.g., Object("JSON").Call("stringify", ...)
|
// e.g., Object("JSON").Call("stringify", ...)
|
||||||
|
|
||||||
function, err := self.Get(name)
|
function, err := o.Get(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Value{}, err
|
return Value{}, err
|
||||||
}
|
}
|
||||||
return function.Call(self.Value(), argumentList...)
|
return function.Call(o.Value(), argumentList...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Value will return self as a value.
|
// Value returns the value of o.
|
||||||
func (self Object) Value() Value {
|
func (o Object) Value() Value {
|
||||||
return self.value
|
return o.value
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the value of the property with the given name.
|
// Get the value of the property with the given name.
|
||||||
func (self Object) Get(name string) (Value, error) {
|
func (o Object) Get(name string) (Value, error) {
|
||||||
value := Value{}
|
value := Value{}
|
||||||
err := catchPanic(func() {
|
err := catchPanic(func() {
|
||||||
value = self.object.get(name)
|
value = o.object.get(name)
|
||||||
})
|
})
|
||||||
if !value.safe() {
|
if !value.safe() {
|
||||||
value = Value{}
|
value = Value{}
|
||||||
|
@ -703,25 +692,23 @@ func (self Object) Get(name string) (Value, error) {
|
||||||
//
|
//
|
||||||
// An error will result if the setting the property triggers an exception (i.e. read-only),
|
// An error will result if the setting the property triggers an exception (i.e. read-only),
|
||||||
// or there is an error during conversion of the given value.
|
// or there is an error during conversion of the given value.
|
||||||
func (self Object) Set(name string, value interface{}) error {
|
func (o Object) Set(name string, value interface{}) error {
|
||||||
{
|
val, err := o.object.runtime.safeToValue(value)
|
||||||
value, err := self.object.runtime.safeToValue(value)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = catchPanic(func() {
|
|
||||||
self.object.put(name, value, true)
|
return catchPanic(func() {
|
||||||
|
o.object.put(name, val, true)
|
||||||
})
|
})
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Keys gets the keys for the given object.
|
// Keys gets the keys for the given object.
|
||||||
//
|
//
|
||||||
// Equivalent to calling Object.keys on the object.
|
// Equivalent to calling Object.keys on the object.
|
||||||
func (self Object) Keys() []string {
|
func (o Object) Keys() []string {
|
||||||
var keys []string
|
var keys []string
|
||||||
self.object.enumerate(false, func(name string) bool {
|
o.object.enumerate(false, func(name string) bool {
|
||||||
keys = append(keys, name)
|
keys = append(keys, name)
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
|
@ -730,10 +717,10 @@ func (self Object) Keys() []string {
|
||||||
|
|
||||||
// KeysByParent gets the keys (and those of the parents) for the given object,
|
// KeysByParent gets the keys (and those of the parents) for the given object,
|
||||||
// in order of "closest" to "furthest".
|
// in order of "closest" to "furthest".
|
||||||
func (self Object) KeysByParent() [][]string {
|
func (o Object) KeysByParent() [][]string {
|
||||||
var a [][]string
|
var a [][]string
|
||||||
|
|
||||||
for o := self.object; o != nil; o = o.prototype {
|
for o := o.object; o != nil; o = o.prototype {
|
||||||
var l []string
|
var l []string
|
||||||
|
|
||||||
o.enumerate(false, func(name string) bool {
|
o.enumerate(false, func(name string) bool {
|
||||||
|
@ -759,28 +746,29 @@ func (self Object) KeysByParent() [][]string {
|
||||||
// Boolean
|
// Boolean
|
||||||
// Date
|
// Date
|
||||||
// RegExp
|
// RegExp
|
||||||
func (self Object) Class() string {
|
func (o Object) Class() string {
|
||||||
return self.object.class
|
return o.object.class
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self Object) MarshalJSON() ([]byte, error) {
|
// MarshalJSON implements json.Marshaller.
|
||||||
|
func (o Object) MarshalJSON() ([]byte, error) {
|
||||||
var goValue interface{}
|
var goValue interface{}
|
||||||
switch value := self.object.value.(type) {
|
switch value := o.object.value.(type) {
|
||||||
case *_goStructObject:
|
case *goStructObject:
|
||||||
goValue = value.value.Interface()
|
goValue = value.value.Interface()
|
||||||
case *_goMapObject:
|
case *goMapObject:
|
||||||
goValue = value.value.Interface()
|
goValue = value.value.Interface()
|
||||||
case *_goArrayObject:
|
case *goArrayObject:
|
||||||
goValue = value.value.Interface()
|
goValue = value.value.Interface()
|
||||||
case *_goSliceObject:
|
case *goSliceObject:
|
||||||
goValue = value.value.Interface()
|
goValue = value.value.Interface()
|
||||||
default:
|
default:
|
||||||
// It's a JS object; pass it to JSON.stringify:
|
// It's a JS object; pass it to JSON.stringify:
|
||||||
var result []byte
|
var result []byte
|
||||||
err := catchPanic(func() {
|
err := catchPanic(func() {
|
||||||
resultVal := builtinJSON_stringify(FunctionCall{
|
resultVal := builtinJSONStringify(FunctionCall{
|
||||||
runtime: self.object.runtime,
|
runtime: o.object.runtime,
|
||||||
ArgumentList: []Value{self.value},
|
ArgumentList: []Value{o.value},
|
||||||
})
|
})
|
||||||
result = []byte(resultVal.String())
|
result = []byte(resultVal.String())
|
||||||
})
|
})
|
||||||
|
|
32
v1/vendor/github.com/robertkrimen/otto/otto_.go
generated
vendored
|
@ -3,28 +3,28 @@ package otto
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"regexp"
|
"regexp"
|
||||||
runtime_ "runtime"
|
goruntime "runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
var isIdentifier_Regexp *regexp.Regexp = regexp.MustCompile(`^[a-zA-Z\$][a-zA-Z0-9\$]*$`)
|
var isIdentifierRegexp *regexp.Regexp = regexp.MustCompile(`^[a-zA-Z\$][a-zA-Z0-9\$]*$`)
|
||||||
|
|
||||||
func isIdentifier(string_ string) bool {
|
func isIdentifier(value string) bool {
|
||||||
return isIdentifier_Regexp.MatchString(string_)
|
return isIdentifierRegexp.MatchString(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_runtime) toValueArray(arguments ...interface{}) []Value {
|
func (rt *runtime) toValueArray(arguments ...interface{}) []Value {
|
||||||
length := len(arguments)
|
length := len(arguments)
|
||||||
if length == 1 {
|
if length == 1 {
|
||||||
if valueArray, ok := arguments[0].([]Value); ok {
|
if valueArray, ok := arguments[0].([]Value); ok {
|
||||||
return valueArray
|
return valueArray
|
||||||
}
|
}
|
||||||
return []Value{self.toValue(arguments[0])}
|
return []Value{rt.toValue(arguments[0])}
|
||||||
}
|
}
|
||||||
|
|
||||||
valueArray := make([]Value, length)
|
valueArray := make([]Value, length)
|
||||||
for index, value := range arguments {
|
for index, value := range arguments {
|
||||||
valueArray[index] = self.toValue(value)
|
valueArray[index] = rt.toValue(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
return valueArray
|
return valueArray
|
||||||
|
@ -89,15 +89,13 @@ func valueToRangeIndex(indexValue Value, length int64, negativeIsZero bool) int6
|
||||||
if index < 0 {
|
if index < 0 {
|
||||||
index = 0
|
index = 0
|
||||||
}
|
}
|
||||||
} else {
|
} else if index > length {
|
||||||
if index > length {
|
|
||||||
index = length
|
index = length
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return index
|
return index
|
||||||
}
|
}
|
||||||
|
|
||||||
func rangeStartEnd(array []Value, size int64, negativeIsZero bool) (start, end int64) {
|
func rangeStartEnd(array []Value, size int64, negativeIsZero bool) (start, end int64) { //nolint: nonamedreturns
|
||||||
start = valueToRangeIndex(valueOfArrayIndex(array, 0), size, negativeIsZero)
|
start = valueToRangeIndex(valueOfArrayIndex(array, 0), size, negativeIsZero)
|
||||||
if len(array) == 1 {
|
if len(array) == 1 {
|
||||||
// If there is only the start argument, then end = size
|
// If there is only the start argument, then end = size
|
||||||
|
@ -115,14 +113,14 @@ func rangeStartEnd(array []Value, size int64, negativeIsZero bool) (start, end i
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func rangeStartLength(source []Value, size int64) (start, length int64) {
|
func rangeStartLength(source []Value, size int64) (start, length int64) { //nolint: nonamedreturns
|
||||||
start = valueToRangeIndex(valueOfArrayIndex(source, 0), size, false)
|
start = valueToRangeIndex(valueOfArrayIndex(source, 0), size, false)
|
||||||
|
|
||||||
// Assume the second argument is missing or undefined
|
// Assume the second argument is missing or undefined
|
||||||
length = int64(size)
|
length = size
|
||||||
if len(source) == 1 {
|
if len(source) == 1 {
|
||||||
// If there is only the start argument, then length = size
|
// If there is only the start argument, then length = size
|
||||||
return
|
return start, length
|
||||||
}
|
}
|
||||||
|
|
||||||
lengthValue := valueOfArrayIndex(source, 1)
|
lengthValue := valueOfArrayIndex(source, 1)
|
||||||
|
@ -130,12 +128,12 @@ func rangeStartLength(source []Value, size int64) (start, length int64) {
|
||||||
// Which it is not, so get the value as an array index
|
// Which it is not, so get the value as an array index
|
||||||
length = lengthValue.number().int64
|
length = lengthValue.number().int64
|
||||||
}
|
}
|
||||||
return
|
return start, length
|
||||||
}
|
}
|
||||||
|
|
||||||
func hereBeDragons(arguments ...interface{}) string {
|
func hereBeDragons(arguments ...interface{}) string {
|
||||||
pc, _, _, _ := runtime_.Caller(1) //nolint: dogsled
|
pc, _, _, _ := goruntime.Caller(1) //nolint: dogsled
|
||||||
name := runtime_.FuncForPC(pc).Name()
|
name := goruntime.FuncForPC(pc).Name()
|
||||||
message := fmt.Sprintf("Here be dragons -- %s", name)
|
message := fmt.Sprintf("Here be dragons -- %s", name)
|
||||||
if len(arguments) > 0 {
|
if len(arguments) > 0 {
|
||||||
message += ": "
|
message += ": "
|
||||||
|
|
4
v1/vendor/github.com/robertkrimen/otto/parser/Makefile
generated
vendored
|
@ -1,4 +0,0 @@
|
||||||
.PHONY: test
|
|
||||||
|
|
||||||
test:
|
|
||||||
go test
|
|
190
v1/vendor/github.com/robertkrimen/otto/parser/README.markdown
generated
vendored
|
@ -1,190 +0,0 @@
|
||||||
# parser
|
|
||||||
--
|
|
||||||
import "github.com/robertkrimen/otto/parser"
|
|
||||||
|
|
||||||
Package parser implements a parser for JavaScript.
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/robertkrimen/otto/parser"
|
|
||||||
)
|
|
||||||
|
|
||||||
Parse and return an AST
|
|
||||||
|
|
||||||
filename := "" // A filename is optional
|
|
||||||
src := `
|
|
||||||
// Sample xyzzy example
|
|
||||||
(function(){
|
|
||||||
if (3.14159 > 0) {
|
|
||||||
console.log("Hello, World.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var xyzzy = NaN;
|
|
||||||
console.log("Nothing happens.");
|
|
||||||
return xyzzy;
|
|
||||||
})();
|
|
||||||
`
|
|
||||||
|
|
||||||
// Parse some JavaScript, yielding a *ast.Program and/or an ErrorList
|
|
||||||
program, err := parser.ParseFile(nil, filename, src, 0)
|
|
||||||
|
|
||||||
|
|
||||||
### Warning
|
|
||||||
|
|
||||||
The parser and AST interfaces are still works-in-progress (particularly where
|
|
||||||
node types are concerned) and may change in the future.
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
#### func ParseFile
|
|
||||||
|
|
||||||
```go
|
|
||||||
func ParseFile(fileSet *file.FileSet, filename string, src interface{}, mode Mode) (*ast.Program, error)
|
|
||||||
```
|
|
||||||
ParseFile parses the source code of a single JavaScript/ECMAScript source file
|
|
||||||
and returns the corresponding ast.Program node.
|
|
||||||
|
|
||||||
If fileSet == nil, ParseFile parses source without a FileSet. If fileSet != nil,
|
|
||||||
ParseFile first adds filename and src to fileSet.
|
|
||||||
|
|
||||||
The filename argument is optional and is used for labelling errors, etc.
|
|
||||||
|
|
||||||
src may be a string, a byte slice, a bytes.Buffer, or an io.Reader, but it MUST
|
|
||||||
always be in UTF-8.
|
|
||||||
|
|
||||||
// Parse some JavaScript, yielding a *ast.Program and/or an ErrorList
|
|
||||||
program, err := parser.ParseFile(nil, "", `if (abc > 1) {}`, 0)
|
|
||||||
|
|
||||||
#### func ParseFunction
|
|
||||||
|
|
||||||
```go
|
|
||||||
func ParseFunction(parameterList, body string) (*ast.FunctionLiteral, error)
|
|
||||||
```
|
|
||||||
ParseFunction parses a given parameter list and body as a function and returns
|
|
||||||
the corresponding ast.FunctionLiteral node.
|
|
||||||
|
|
||||||
The parameter list, if any, should be a comma-separated list of identifiers.
|
|
||||||
|
|
||||||
#### func ReadSource
|
|
||||||
|
|
||||||
```go
|
|
||||||
func ReadSource(filename string, src interface{}) ([]byte, error)
|
|
||||||
```
|
|
||||||
|
|
||||||
#### func TransformRegExp
|
|
||||||
|
|
||||||
```go
|
|
||||||
func TransformRegExp(pattern string) (string, error)
|
|
||||||
```
|
|
||||||
TransformRegExp transforms a JavaScript pattern into a Go "regexp" pattern.
|
|
||||||
|
|
||||||
re2 (Go) cannot do backtracking, so the presence of a lookahead (?=) (?!) or
|
|
||||||
backreference (\1, \2, ...) will cause an error.
|
|
||||||
|
|
||||||
re2 (Go) has a different definition for \s: [\t\n\f\r ]. The JavaScript
|
|
||||||
definition, on the other hand, also includes \v, Unicode "Separator, Space",
|
|
||||||
etc.
|
|
||||||
|
|
||||||
If the pattern is invalid (not valid even in JavaScript), then this function
|
|
||||||
returns the empty string and an error.
|
|
||||||
|
|
||||||
If the pattern is valid, but incompatible (contains a lookahead or
|
|
||||||
backreference), then this function returns the transformation (a non-empty
|
|
||||||
string) AND an error.
|
|
||||||
|
|
||||||
#### type Error
|
|
||||||
|
|
||||||
```go
|
|
||||||
type Error struct {
|
|
||||||
Position file.Position
|
|
||||||
Message string
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
An Error represents a parsing error. It includes the position where the error
|
|
||||||
occurred and a message/description.
|
|
||||||
|
|
||||||
#### func (Error) Error
|
|
||||||
|
|
||||||
```go
|
|
||||||
func (self Error) Error() string
|
|
||||||
```
|
|
||||||
|
|
||||||
#### type ErrorList
|
|
||||||
|
|
||||||
```go
|
|
||||||
type ErrorList []*Error
|
|
||||||
```
|
|
||||||
|
|
||||||
ErrorList is a list of *Errors.
|
|
||||||
|
|
||||||
#### func (*ErrorList) Add
|
|
||||||
|
|
||||||
```go
|
|
||||||
func (self *ErrorList) Add(position file.Position, msg string)
|
|
||||||
```
|
|
||||||
Add adds an Error with given position and message to an ErrorList.
|
|
||||||
|
|
||||||
#### func (ErrorList) Err
|
|
||||||
|
|
||||||
```go
|
|
||||||
func (self ErrorList) Err() error
|
|
||||||
```
|
|
||||||
Err returns an error equivalent to this ErrorList. If the list is empty, Err
|
|
||||||
returns nil.
|
|
||||||
|
|
||||||
#### func (ErrorList) Error
|
|
||||||
|
|
||||||
```go
|
|
||||||
func (self ErrorList) Error() string
|
|
||||||
```
|
|
||||||
Error implements the Error interface.
|
|
||||||
|
|
||||||
#### func (ErrorList) Len
|
|
||||||
|
|
||||||
```go
|
|
||||||
func (self ErrorList) Len() int
|
|
||||||
```
|
|
||||||
|
|
||||||
#### func (ErrorList) Less
|
|
||||||
|
|
||||||
```go
|
|
||||||
func (self ErrorList) Less(i, j int) bool
|
|
||||||
```
|
|
||||||
|
|
||||||
#### func (*ErrorList) Reset
|
|
||||||
|
|
||||||
```go
|
|
||||||
func (self *ErrorList) Reset()
|
|
||||||
```
|
|
||||||
Reset resets an ErrorList to no errors.
|
|
||||||
|
|
||||||
#### func (ErrorList) Sort
|
|
||||||
|
|
||||||
```go
|
|
||||||
func (self ErrorList) Sort()
|
|
||||||
```
|
|
||||||
|
|
||||||
#### func (ErrorList) Swap
|
|
||||||
|
|
||||||
```go
|
|
||||||
func (self ErrorList) Swap(i, j int)
|
|
||||||
```
|
|
||||||
|
|
||||||
#### type Mode
|
|
||||||
|
|
||||||
```go
|
|
||||||
type Mode uint
|
|
||||||
```
|
|
||||||
|
|
||||||
A Mode value is a set of flags (or 0). They control optional parser
|
|
||||||
functionality.
|
|
||||||
|
|
||||||
```go
|
|
||||||
const (
|
|
||||||
IgnoreRegExpErrors Mode = 1 << iota // Ignore RegExp compatibility errors (allow backtracking)
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
--
|
|
||||||
**godocdown** http://github.com/robertkrimen/godocdown
|
|
102
v1/vendor/github.com/robertkrimen/otto/parser/error.go
generated
vendored
|
@ -9,8 +9,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
err_UnexpectedToken = "Unexpected token %v"
|
errUnexpectedToken = "Unexpected token %v"
|
||||||
err_UnexpectedEndOfInput = "Unexpected end of input"
|
errUnexpectedEndOfInput = "Unexpected end of input"
|
||||||
)
|
)
|
||||||
|
|
||||||
// UnexpectedNumber: 'Unexpected number',
|
// UnexpectedNumber: 'Unexpected number',
|
||||||
|
@ -20,7 +20,7 @@ const (
|
||||||
// NewlineAfterThrow: 'Illegal newline after throw',
|
// NewlineAfterThrow: 'Illegal newline after throw',
|
||||||
// InvalidRegExp: 'Invalid regular expression',
|
// InvalidRegExp: 'Invalid regular expression',
|
||||||
// UnterminatedRegExp: 'Invalid regular expression: missing /',
|
// UnterminatedRegExp: 'Invalid regular expression: missing /',
|
||||||
// InvalidLHSInAssignment: 'Invalid left-hand side in assignment',
|
// InvalidLHSInAssignment: 'invalid left-hand side in assignment',
|
||||||
// InvalidLHSInForIn: 'Invalid left-hand side in for-in',
|
// InvalidLHSInForIn: 'Invalid left-hand side in for-in',
|
||||||
// MultipleDefaultsInSwitch: 'More than one default clause in switch statement',
|
// MultipleDefaultsInSwitch: 'More than one default clause in switch statement',
|
||||||
// NoCatchOrFinally: 'Missing catch or finally after try',
|
// NoCatchOrFinally: 'Missing catch or finally after try',
|
||||||
|
@ -55,27 +55,27 @@ type Error struct {
|
||||||
|
|
||||||
// FIXME Should this be "SyntaxError"?
|
// FIXME Should this be "SyntaxError"?
|
||||||
|
|
||||||
func (self Error) Error() string {
|
func (e Error) Error() string {
|
||||||
filename := self.Position.Filename
|
filename := e.Position.Filename
|
||||||
if filename == "" {
|
if filename == "" {
|
||||||
filename = "(anonymous)"
|
filename = "(anonymous)"
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("%s: Line %d:%d %s",
|
return fmt.Sprintf("%s: Line %d:%d %s",
|
||||||
filename,
|
filename,
|
||||||
self.Position.Line,
|
e.Position.Line,
|
||||||
self.Position.Column,
|
e.Position.Column,
|
||||||
self.Message,
|
e.Message,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_parser) error(place interface{}, msg string, msgValues ...interface{}) *Error {
|
func (p *parser) error(place interface{}, msg string, msgValues ...interface{}) {
|
||||||
var idx file.Idx
|
var idx file.Idx
|
||||||
switch place := place.(type) {
|
switch place := place.(type) {
|
||||||
case int:
|
case int:
|
||||||
idx = self.idxOf(place)
|
idx = p.idxOf(place)
|
||||||
case file.Idx:
|
case file.Idx:
|
||||||
if place == 0 {
|
if place == 0 {
|
||||||
idx = self.idxOf(self.chrOffset)
|
idx = p.idxOf(p.chrOffset)
|
||||||
} else {
|
} else {
|
||||||
idx = place
|
idx = place
|
||||||
}
|
}
|
||||||
|
@ -83,57 +83,69 @@ func (self *_parser) error(place interface{}, msg string, msgValues ...interface
|
||||||
panic(fmt.Errorf("error(%T, ...)", place))
|
panic(fmt.Errorf("error(%T, ...)", place))
|
||||||
}
|
}
|
||||||
|
|
||||||
position := self.position(idx)
|
position := p.position(idx)
|
||||||
msg = fmt.Sprintf(msg, msgValues...)
|
msg = fmt.Sprintf(msg, msgValues...)
|
||||||
self.errors.Add(position, msg)
|
p.errors.Add(position, msg)
|
||||||
return self.errors[len(self.errors)-1]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_parser) errorUnexpected(idx file.Idx, chr rune) error {
|
func (p *parser) errorUnexpected(idx file.Idx, chr rune) {
|
||||||
if chr == -1 {
|
if chr == -1 {
|
||||||
return self.error(idx, err_UnexpectedEndOfInput)
|
p.error(idx, errUnexpectedEndOfInput)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
return self.error(idx, err_UnexpectedToken, token.ILLEGAL)
|
p.error(idx, errUnexpectedToken, token.ILLEGAL)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_parser) errorUnexpectedToken(tkn token.Token) error {
|
func (p *parser) errorUnexpectedToken(tkn token.Token) {
|
||||||
switch tkn {
|
if tkn == token.EOF {
|
||||||
case token.EOF:
|
p.error(file.Idx(0), errUnexpectedEndOfInput)
|
||||||
return self.error(file.Idx(0), err_UnexpectedEndOfInput)
|
return
|
||||||
}
|
}
|
||||||
value := tkn.String()
|
value := tkn.String()
|
||||||
switch tkn {
|
switch tkn {
|
||||||
case token.BOOLEAN, token.NULL:
|
case token.BOOLEAN, token.NULL:
|
||||||
value = self.literal
|
p.error(p.idx, errUnexpectedToken, p.literal)
|
||||||
case token.IDENTIFIER:
|
case token.IDENTIFIER:
|
||||||
return self.error(self.idx, "Unexpected identifier")
|
p.error(p.idx, "Unexpected identifier")
|
||||||
case token.KEYWORD:
|
case token.KEYWORD:
|
||||||
// TODO Might be a future reserved word
|
// TODO Might be a future reserved word
|
||||||
return self.error(self.idx, "Unexpected reserved word")
|
p.error(p.idx, "Unexpected reserved word")
|
||||||
case token.NUMBER:
|
case token.NUMBER:
|
||||||
return self.error(self.idx, "Unexpected number")
|
p.error(p.idx, "Unexpected number")
|
||||||
case token.STRING:
|
case token.STRING:
|
||||||
return self.error(self.idx, "Unexpected string")
|
p.error(p.idx, "Unexpected string")
|
||||||
|
default:
|
||||||
|
p.error(p.idx, errUnexpectedToken, value)
|
||||||
}
|
}
|
||||||
return self.error(self.idx, err_UnexpectedToken, value)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ErrorList is a list of *Errors.
|
// ErrorList is a list of *Errors.
|
||||||
type ErrorList []*Error //nolint: errname
|
type ErrorList []*Error //nolint: errname
|
||||||
|
|
||||||
// Add adds an Error with given position and message to an ErrorList.
|
// Add adds an Error with given position and message to an ErrorList.
|
||||||
func (self *ErrorList) Add(position file.Position, msg string) {
|
func (el *ErrorList) Add(position file.Position, msg string) {
|
||||||
*self = append(*self, &Error{position, msg})
|
*el = append(*el, &Error{position, msg})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset resets an ErrorList to no errors.
|
// Reset resets an ErrorList to no errors.
|
||||||
func (self *ErrorList) Reset() { *self = (*self)[0:0] }
|
func (el *ErrorList) Reset() {
|
||||||
|
*el = (*el)[0:0]
|
||||||
|
}
|
||||||
|
|
||||||
func (self ErrorList) Len() int { return len(self) }
|
// Len implement sort.Interface.
|
||||||
func (self ErrorList) Swap(i, j int) { self[i], self[j] = self[j], self[i] }
|
func (el *ErrorList) Len() int {
|
||||||
func (self ErrorList) Less(i, j int) bool {
|
return len(*el)
|
||||||
x := &self[i].Position
|
}
|
||||||
y := &self[j].Position
|
|
||||||
|
// Swap implement sort.Interface.
|
||||||
|
func (el *ErrorList) Swap(i, j int) {
|
||||||
|
(*el)[i], (*el)[j] = (*el)[j], (*el)[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Less implement sort.Interface.
|
||||||
|
func (el *ErrorList) Less(i, j int) bool {
|
||||||
|
x := (*el)[i].Position
|
||||||
|
y := (*el)[j].Position
|
||||||
if x.Filename < y.Filename {
|
if x.Filename < y.Filename {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -148,26 +160,28 @@ func (self ErrorList) Less(i, j int) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self ErrorList) Sort() {
|
// Sort sorts el.
|
||||||
sort.Sort(self)
|
func (el *ErrorList) Sort() {
|
||||||
|
sort.Sort(el)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Error implements the Error interface.
|
// Error implements the Error interface.
|
||||||
func (self ErrorList) Error() string {
|
func (el *ErrorList) Error() string {
|
||||||
switch len(self) {
|
switch len(*el) {
|
||||||
case 0:
|
case 0:
|
||||||
return "no errors"
|
return "no errors"
|
||||||
case 1:
|
case 1:
|
||||||
return self[0].Error()
|
return (*el)[0].Error()
|
||||||
|
default:
|
||||||
|
return fmt.Sprintf("%s (and %d more errors)", (*el)[0].Error(), len(*el)-1)
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("%s (and %d more errors)", self[0].Error(), len(self)-1)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Err returns an error equivalent to this ErrorList.
|
// Err returns an error equivalent to this ErrorList.
|
||||||
// If the list is empty, Err returns nil.
|
// If the list is empty, Err returns nil.
|
||||||
func (self ErrorList) Err() error {
|
func (el *ErrorList) Err() error {
|
||||||
if len(self) == 0 {
|
if len(*el) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return self
|
return el
|
||||||
}
|
}
|
||||||
|
|
730
v1/vendor/github.com/robertkrimen/otto/parser/expression.go
generated
vendored
552
v1/vendor/github.com/robertkrimen/otto/parser/lexer.go
generated
vendored
|
@ -15,7 +15,7 @@ import (
|
||||||
"github.com/robertkrimen/otto/token"
|
"github.com/robertkrimen/otto/token"
|
||||||
)
|
)
|
||||||
|
|
||||||
type _chr struct {
|
type chr struct { //nolint: unused
|
||||||
value rune
|
value rune
|
||||||
width int
|
width int
|
||||||
}
|
}
|
||||||
|
@ -55,49 +55,50 @@ func isIdentifierPart(chr rune) bool {
|
||||||
chr >= utf8.RuneSelf && (unicode.IsLetter(chr) || unicode.IsDigit(chr))
|
chr >= utf8.RuneSelf && (unicode.IsLetter(chr) || unicode.IsDigit(chr))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_parser) scanIdentifier() (string, error) {
|
func (p *parser) scanIdentifier() (string, error) {
|
||||||
offset := self.chrOffset
|
offset := p.chrOffset
|
||||||
parse := false
|
parse := false
|
||||||
for isIdentifierPart(self.chr) {
|
for isIdentifierPart(p.chr) {
|
||||||
if self.chr == '\\' {
|
if p.chr == '\\' {
|
||||||
distance := self.chrOffset - offset
|
distance := p.chrOffset - offset
|
||||||
self.read()
|
p.read()
|
||||||
if self.chr != 'u' {
|
if p.chr != 'u' {
|
||||||
return "", fmt.Errorf("Invalid identifier escape character: %c (%s)", self.chr, string(self.chr))
|
return "", fmt.Errorf("invalid identifier escape character: %c (%s)", p.chr, string(p.chr))
|
||||||
}
|
}
|
||||||
parse = true
|
parse = true
|
||||||
var value rune
|
var value rune
|
||||||
for j := 0; j < 4; j++ {
|
for j := 0; j < 4; j++ {
|
||||||
self.read()
|
p.read()
|
||||||
decimal, ok := hex2decimal(byte(self.chr))
|
decimal, ok := hex2decimal(byte(p.chr))
|
||||||
if !ok {
|
if !ok {
|
||||||
return "", fmt.Errorf("Invalid identifier escape character: %c (%s)", self.chr, string(self.chr))
|
return "", fmt.Errorf("invalid identifier escape character: %c (%s)", p.chr, string(p.chr))
|
||||||
}
|
}
|
||||||
value = value<<4 | decimal
|
value = value<<4 | decimal
|
||||||
}
|
}
|
||||||
if value == '\\' {
|
switch {
|
||||||
return "", fmt.Errorf("Invalid identifier escape value: %c (%s)", value, string(value))
|
case value == '\\':
|
||||||
} else if distance == 0 {
|
return "", fmt.Errorf("invalid identifier escape value: %c (%s)", value, string(value))
|
||||||
|
case distance == 0:
|
||||||
if !isIdentifierStart(value) {
|
if !isIdentifierStart(value) {
|
||||||
return "", fmt.Errorf("Invalid identifier escape value: %c (%s)", value, string(value))
|
return "", fmt.Errorf("invalid identifier escape value: %c (%s)", value, string(value))
|
||||||
}
|
}
|
||||||
} else if distance > 0 {
|
case distance > 0:
|
||||||
if !isIdentifierPart(value) {
|
if !isIdentifierPart(value) {
|
||||||
return "", fmt.Errorf("Invalid identifier escape value: %c (%s)", value, string(value))
|
return "", fmt.Errorf("invalid identifier escape value: %c (%s)", value, string(value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.read()
|
p.read()
|
||||||
}
|
}
|
||||||
literal := string(self.str[offset:self.chrOffset])
|
literal := p.str[offset:p.chrOffset]
|
||||||
if parse {
|
if parse {
|
||||||
return parseStringLiteral(literal)
|
return parseStringLiteral(literal)
|
||||||
}
|
}
|
||||||
return literal, nil
|
return literal, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 7.2
|
// 7.2.
|
||||||
func isLineWhiteSpace(chr rune) bool {
|
func isLineWhiteSpace(chr rune) bool { //nolint: unused, deadcode
|
||||||
switch chr {
|
switch chr {
|
||||||
case '\u0009', '\u000b', '\u000c', '\u0020', '\u00a0', '\ufeff':
|
case '\u0009', '\u000b', '\u000c', '\u0020', '\u00a0', '\ufeff':
|
||||||
return true
|
return true
|
||||||
|
@ -109,7 +110,7 @@ func isLineWhiteSpace(chr rune) bool {
|
||||||
return unicode.IsSpace(chr)
|
return unicode.IsSpace(chr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 7.3
|
// 7.3.
|
||||||
func isLineTerminator(chr rune) bool {
|
func isLineTerminator(chr rune) bool {
|
||||||
switch chr {
|
switch chr {
|
||||||
case '\u000a', '\u000d', '\u2028', '\u2029':
|
case '\u000a', '\u000d', '\u2028', '\u2029':
|
||||||
|
@ -118,19 +119,19 @@ func isLineTerminator(chr rune) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_parser) scan() (tkn token.Token, literal string, idx file.Idx) {
|
func (p *parser) scan() (tkn token.Token, literal string, idx file.Idx) { //nolint: nonamedreturns
|
||||||
self.implicitSemicolon = false
|
p.implicitSemicolon = false
|
||||||
|
|
||||||
for {
|
for {
|
||||||
self.skipWhiteSpace()
|
p.skipWhiteSpace()
|
||||||
|
|
||||||
idx = self.idxOf(self.chrOffset)
|
idx = p.idxOf(p.chrOffset)
|
||||||
insertSemicolon := false
|
insertSemicolon := false
|
||||||
|
|
||||||
switch chr := self.chr; {
|
switch chr := p.chr; {
|
||||||
case isIdentifierStart(chr):
|
case isIdentifierStart(chr):
|
||||||
var err error
|
var err error
|
||||||
literal, err = self.scanIdentifier()
|
literal, err = p.scanIdentifier()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
tkn = token.ILLEGAL
|
tkn = token.ILLEGAL
|
||||||
break
|
break
|
||||||
|
@ -142,23 +143,20 @@ func (self *_parser) scan() (tkn token.Token, literal string, idx file.Idx) {
|
||||||
|
|
||||||
switch tkn {
|
switch tkn {
|
||||||
case 0: // Not a keyword
|
case 0: // Not a keyword
|
||||||
if literal == "true" || literal == "false" {
|
switch literal {
|
||||||
self.insertSemicolon = true
|
case "true", "false":
|
||||||
tkn = token.BOOLEAN
|
p.insertSemicolon = true
|
||||||
return
|
return token.BOOLEAN, literal, idx
|
||||||
} else if literal == "null" {
|
case "null":
|
||||||
self.insertSemicolon = true
|
p.insertSemicolon = true
|
||||||
tkn = token.NULL
|
return token.NULL, literal, idx
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case token.KEYWORD:
|
case token.KEYWORD:
|
||||||
tkn = token.KEYWORD
|
|
||||||
if strict {
|
if strict {
|
||||||
// TODO If strict and in strict mode, then this is not a break
|
// TODO If strict and in strict mode, then this is not a break
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
return
|
return token.KEYWORD, literal, idx
|
||||||
|
|
||||||
case
|
case
|
||||||
token.THIS,
|
token.THIS,
|
||||||
|
@ -167,40 +165,39 @@ func (self *_parser) scan() (tkn token.Token, literal string, idx file.Idx) {
|
||||||
token.RETURN,
|
token.RETURN,
|
||||||
token.CONTINUE,
|
token.CONTINUE,
|
||||||
token.DEBUGGER:
|
token.DEBUGGER:
|
||||||
self.insertSemicolon = true
|
p.insertSemicolon = true
|
||||||
return
|
return tkn, literal, idx
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return
|
return tkn, literal, idx
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.insertSemicolon = true
|
p.insertSemicolon = true
|
||||||
tkn = token.IDENTIFIER
|
return token.IDENTIFIER, literal, idx
|
||||||
return
|
|
||||||
case '0' <= chr && chr <= '9':
|
case '0' <= chr && chr <= '9':
|
||||||
self.insertSemicolon = true
|
p.insertSemicolon = true
|
||||||
tkn, literal = self.scanNumericLiteral(false)
|
tkn, literal = p.scanNumericLiteral(false)
|
||||||
return
|
return tkn, literal, idx
|
||||||
default:
|
default:
|
||||||
self.read()
|
p.read()
|
||||||
switch chr {
|
switch chr {
|
||||||
case -1:
|
case -1:
|
||||||
if self.insertSemicolon {
|
if p.insertSemicolon {
|
||||||
self.insertSemicolon = false
|
p.insertSemicolon = false
|
||||||
self.implicitSemicolon = true
|
p.implicitSemicolon = true
|
||||||
}
|
}
|
||||||
tkn = token.EOF
|
tkn = token.EOF
|
||||||
case '\r', '\n', '\u2028', '\u2029':
|
case '\r', '\n', '\u2028', '\u2029':
|
||||||
self.insertSemicolon = false
|
p.insertSemicolon = false
|
||||||
self.implicitSemicolon = true
|
p.implicitSemicolon = true
|
||||||
self.comments.AtLineBreak()
|
p.comments.AtLineBreak()
|
||||||
continue
|
continue
|
||||||
case ':':
|
case ':':
|
||||||
tkn = token.COLON
|
tkn = token.COLON
|
||||||
case '.':
|
case '.':
|
||||||
if digitValue(self.chr) < 10 {
|
if digitValue(p.chr) < 10 {
|
||||||
insertSemicolon = true
|
insertSemicolon = true
|
||||||
tkn, literal = self.scanNumericLiteral(true)
|
tkn, literal = p.scanNumericLiteral(true)
|
||||||
} else {
|
} else {
|
||||||
tkn = token.PERIOD
|
tkn = token.PERIOD
|
||||||
}
|
}
|
||||||
|
@ -224,68 +221,69 @@ func (self *_parser) scan() (tkn token.Token, literal string, idx file.Idx) {
|
||||||
tkn = token.RIGHT_BRACE
|
tkn = token.RIGHT_BRACE
|
||||||
insertSemicolon = true
|
insertSemicolon = true
|
||||||
case '+':
|
case '+':
|
||||||
tkn = self.switch3(token.PLUS, token.ADD_ASSIGN, '+', token.INCREMENT)
|
tkn = p.switch3(token.PLUS, token.ADD_ASSIGN, '+', token.INCREMENT)
|
||||||
if tkn == token.INCREMENT {
|
if tkn == token.INCREMENT {
|
||||||
insertSemicolon = true
|
insertSemicolon = true
|
||||||
}
|
}
|
||||||
case '-':
|
case '-':
|
||||||
tkn = self.switch3(token.MINUS, token.SUBTRACT_ASSIGN, '-', token.DECREMENT)
|
tkn = p.switch3(token.MINUS, token.SUBTRACT_ASSIGN, '-', token.DECREMENT)
|
||||||
if tkn == token.DECREMENT {
|
if tkn == token.DECREMENT {
|
||||||
insertSemicolon = true
|
insertSemicolon = true
|
||||||
}
|
}
|
||||||
case '*':
|
case '*':
|
||||||
tkn = self.switch2(token.MULTIPLY, token.MULTIPLY_ASSIGN)
|
tkn = p.switch2(token.MULTIPLY, token.MULTIPLY_ASSIGN)
|
||||||
case '/':
|
case '/':
|
||||||
if self.chr == '/' {
|
switch p.chr {
|
||||||
if self.mode&StoreComments != 0 {
|
case '/':
|
||||||
literal := string(self.readSingleLineComment())
|
if p.mode&StoreComments != 0 {
|
||||||
self.comments.AddComment(ast.NewComment(literal, self.idx))
|
literal := string(p.readSingleLineComment())
|
||||||
|
p.comments.AddComment(ast.NewComment(literal, idx))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
self.skipSingleLineComment()
|
p.skipSingleLineComment()
|
||||||
continue
|
continue
|
||||||
} else if self.chr == '*' {
|
case '*':
|
||||||
if self.mode&StoreComments != 0 {
|
if p.mode&StoreComments != 0 {
|
||||||
literal = string(self.readMultiLineComment())
|
literal = string(p.readMultiLineComment())
|
||||||
self.comments.AddComment(ast.NewComment(literal, self.idx))
|
p.comments.AddComment(ast.NewComment(literal, idx))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
self.skipMultiLineComment()
|
p.skipMultiLineComment()
|
||||||
continue
|
continue
|
||||||
} else {
|
default:
|
||||||
// Could be division, could be RegExp literal
|
// Could be division, could be RegExp literal
|
||||||
tkn = self.switch2(token.SLASH, token.QUOTIENT_ASSIGN)
|
tkn = p.switch2(token.SLASH, token.QUOTIENT_ASSIGN)
|
||||||
insertSemicolon = true
|
insertSemicolon = true
|
||||||
}
|
}
|
||||||
case '%':
|
case '%':
|
||||||
tkn = self.switch2(token.REMAINDER, token.REMAINDER_ASSIGN)
|
tkn = p.switch2(token.REMAINDER, token.REMAINDER_ASSIGN)
|
||||||
case '^':
|
case '^':
|
||||||
tkn = self.switch2(token.EXCLUSIVE_OR, token.EXCLUSIVE_OR_ASSIGN)
|
tkn = p.switch2(token.EXCLUSIVE_OR, token.EXCLUSIVE_OR_ASSIGN)
|
||||||
case '<':
|
case '<':
|
||||||
tkn = self.switch4(token.LESS, token.LESS_OR_EQUAL, '<', token.SHIFT_LEFT, token.SHIFT_LEFT_ASSIGN)
|
tkn = p.switch4(token.LESS, token.LESS_OR_EQUAL, '<', token.SHIFT_LEFT, token.SHIFT_LEFT_ASSIGN)
|
||||||
case '>':
|
case '>':
|
||||||
tkn = self.switch6(token.GREATER, token.GREATER_OR_EQUAL, '>', token.SHIFT_RIGHT, token.SHIFT_RIGHT_ASSIGN, '>', token.UNSIGNED_SHIFT_RIGHT, token.UNSIGNED_SHIFT_RIGHT_ASSIGN)
|
tkn = p.switch6(token.GREATER, token.GREATER_OR_EQUAL, '>', token.SHIFT_RIGHT, token.SHIFT_RIGHT_ASSIGN, '>', token.UNSIGNED_SHIFT_RIGHT, token.UNSIGNED_SHIFT_RIGHT_ASSIGN)
|
||||||
case '=':
|
case '=':
|
||||||
tkn = self.switch2(token.ASSIGN, token.EQUAL)
|
tkn = p.switch2(token.ASSIGN, token.EQUAL)
|
||||||
if tkn == token.EQUAL && self.chr == '=' {
|
if tkn == token.EQUAL && p.chr == '=' {
|
||||||
self.read()
|
p.read()
|
||||||
tkn = token.STRICT_EQUAL
|
tkn = token.STRICT_EQUAL
|
||||||
}
|
}
|
||||||
case '!':
|
case '!':
|
||||||
tkn = self.switch2(token.NOT, token.NOT_EQUAL)
|
tkn = p.switch2(token.NOT, token.NOT_EQUAL)
|
||||||
if tkn == token.NOT_EQUAL && self.chr == '=' {
|
if tkn == token.NOT_EQUAL && p.chr == '=' {
|
||||||
self.read()
|
p.read()
|
||||||
tkn = token.STRICT_NOT_EQUAL
|
tkn = token.STRICT_NOT_EQUAL
|
||||||
}
|
}
|
||||||
case '&':
|
case '&':
|
||||||
if self.chr == '^' {
|
if p.chr == '^' {
|
||||||
self.read()
|
p.read()
|
||||||
tkn = self.switch2(token.AND_NOT, token.AND_NOT_ASSIGN)
|
tkn = p.switch2(token.AND_NOT, token.AND_NOT_ASSIGN)
|
||||||
} else {
|
} else {
|
||||||
tkn = self.switch3(token.AND, token.AND_ASSIGN, '&', token.LOGICAL_AND)
|
tkn = p.switch3(token.AND, token.AND_ASSIGN, '&', token.LOGICAL_AND)
|
||||||
}
|
}
|
||||||
case '|':
|
case '|':
|
||||||
tkn = self.switch3(token.OR, token.OR_ASSIGN, '|', token.LOGICAL_OR)
|
tkn = p.switch3(token.OR, token.OR_ASSIGN, '|', token.LOGICAL_OR)
|
||||||
case '~':
|
case '~':
|
||||||
tkn = token.BITWISE_NOT
|
tkn = token.BITWISE_NOT
|
||||||
case '?':
|
case '?':
|
||||||
|
@ -294,49 +292,49 @@ func (self *_parser) scan() (tkn token.Token, literal string, idx file.Idx) {
|
||||||
insertSemicolon = true
|
insertSemicolon = true
|
||||||
tkn = token.STRING
|
tkn = token.STRING
|
||||||
var err error
|
var err error
|
||||||
literal, err = self.scanString(self.chrOffset - 1)
|
literal, err = p.scanString(p.chrOffset - 1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
tkn = token.ILLEGAL
|
tkn = token.ILLEGAL
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
self.errorUnexpected(idx, chr)
|
p.errorUnexpected(idx, chr)
|
||||||
tkn = token.ILLEGAL
|
tkn = token.ILLEGAL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.insertSemicolon = insertSemicolon
|
p.insertSemicolon = insertSemicolon
|
||||||
return
|
return tkn, literal, idx
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_parser) switch2(tkn0, tkn1 token.Token) token.Token {
|
func (p *parser) switch2(tkn0, tkn1 token.Token) token.Token {
|
||||||
if self.chr == '=' {
|
if p.chr == '=' {
|
||||||
self.read()
|
p.read()
|
||||||
return tkn1
|
return tkn1
|
||||||
}
|
}
|
||||||
return tkn0
|
return tkn0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_parser) switch3(tkn0, tkn1 token.Token, chr2 rune, tkn2 token.Token) token.Token {
|
func (p *parser) switch3(tkn0, tkn1 token.Token, chr2 rune, tkn2 token.Token) token.Token {
|
||||||
if self.chr == '=' {
|
if p.chr == '=' {
|
||||||
self.read()
|
p.read()
|
||||||
return tkn1
|
return tkn1
|
||||||
}
|
}
|
||||||
if self.chr == chr2 {
|
if p.chr == chr2 {
|
||||||
self.read()
|
p.read()
|
||||||
return tkn2
|
return tkn2
|
||||||
}
|
}
|
||||||
return tkn0
|
return tkn0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_parser) switch4(tkn0, tkn1 token.Token, chr2 rune, tkn2, tkn3 token.Token) token.Token {
|
func (p *parser) switch4(tkn0, tkn1 token.Token, chr2 rune, tkn2, tkn3 token.Token) token.Token {
|
||||||
if self.chr == '=' {
|
if p.chr == '=' {
|
||||||
self.read()
|
p.read()
|
||||||
return tkn1
|
return tkn1
|
||||||
}
|
}
|
||||||
if self.chr == chr2 {
|
if p.chr == chr2 {
|
||||||
self.read()
|
p.read()
|
||||||
if self.chr == '=' {
|
if p.chr == '=' {
|
||||||
self.read()
|
p.read()
|
||||||
return tkn3
|
return tkn3
|
||||||
}
|
}
|
||||||
return tkn2
|
return tkn2
|
||||||
|
@ -344,21 +342,21 @@ func (self *_parser) switch4(tkn0, tkn1 token.Token, chr2 rune, tkn2, tkn3 token
|
||||||
return tkn0
|
return tkn0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_parser) switch6(tkn0, tkn1 token.Token, chr2 rune, tkn2, tkn3 token.Token, chr3 rune, tkn4, tkn5 token.Token) token.Token {
|
func (p *parser) switch6(tkn0, tkn1 token.Token, chr2 rune, tkn2, tkn3 token.Token, chr3 rune, tkn4, tkn5 token.Token) token.Token {
|
||||||
if self.chr == '=' {
|
if p.chr == '=' {
|
||||||
self.read()
|
p.read()
|
||||||
return tkn1
|
return tkn1
|
||||||
}
|
}
|
||||||
if self.chr == chr2 {
|
if p.chr == chr2 {
|
||||||
self.read()
|
p.read()
|
||||||
if self.chr == '=' {
|
if p.chr == '=' {
|
||||||
self.read()
|
p.read()
|
||||||
return tkn3
|
return tkn3
|
||||||
}
|
}
|
||||||
if self.chr == chr3 {
|
if p.chr == chr3 {
|
||||||
self.read()
|
p.read()
|
||||||
if self.chr == '=' {
|
if p.chr == '=' {
|
||||||
self.read()
|
p.read()
|
||||||
return tkn5
|
return tkn5
|
||||||
}
|
}
|
||||||
return tkn4
|
return tkn4
|
||||||
|
@ -368,137 +366,137 @@ func (self *_parser) switch6(tkn0, tkn1 token.Token, chr2 rune, tkn2, tkn3 token
|
||||||
return tkn0
|
return tkn0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_parser) chrAt(index int) _chr {
|
func (p *parser) chrAt(index int) chr { //nolint: unused
|
||||||
value, width := utf8.DecodeRuneInString(self.str[index:])
|
value, width := utf8.DecodeRuneInString(p.str[index:])
|
||||||
return _chr{
|
return chr{
|
||||||
value: value,
|
value: value,
|
||||||
width: width,
|
width: width,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_parser) _peek() rune {
|
func (p *parser) peek() rune {
|
||||||
if self.offset+1 < self.length {
|
if p.offset+1 < p.length {
|
||||||
return rune(self.str[self.offset+1])
|
return rune(p.str[p.offset+1])
|
||||||
}
|
}
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_parser) read() {
|
func (p *parser) read() {
|
||||||
if self.offset < self.length {
|
if p.offset < p.length {
|
||||||
self.chrOffset = self.offset
|
p.chrOffset = p.offset
|
||||||
chr, width := rune(self.str[self.offset]), 1
|
chr, width := rune(p.str[p.offset]), 1
|
||||||
if chr >= utf8.RuneSelf { // !ASCII
|
if chr >= utf8.RuneSelf { // !ASCII
|
||||||
chr, width = utf8.DecodeRuneInString(self.str[self.offset:])
|
chr, width = utf8.DecodeRuneInString(p.str[p.offset:])
|
||||||
if chr == utf8.RuneError && width == 1 {
|
if chr == utf8.RuneError && width == 1 {
|
||||||
self.error(self.chrOffset, "Invalid UTF-8 character")
|
p.error(p.chrOffset, "Invalid UTF-8 character")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.offset += width
|
p.offset += width
|
||||||
self.chr = chr
|
p.chr = chr
|
||||||
} else {
|
} else {
|
||||||
self.chrOffset = self.length
|
p.chrOffset = p.length
|
||||||
self.chr = -1 // EOF
|
p.chr = -1 // EOF
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is here since the functions are so similar
|
// This is here since the functions are so similar.
|
||||||
func (self *_RegExp_parser) read() {
|
func (p *regExpParser) read() {
|
||||||
if self.offset < self.length {
|
if p.offset < p.length {
|
||||||
self.chrOffset = self.offset
|
p.chrOffset = p.offset
|
||||||
chr, width := rune(self.str[self.offset]), 1
|
chr, width := rune(p.str[p.offset]), 1
|
||||||
if chr >= utf8.RuneSelf { // !ASCII
|
if chr >= utf8.RuneSelf { // !ASCII
|
||||||
chr, width = utf8.DecodeRuneInString(self.str[self.offset:])
|
chr, width = utf8.DecodeRuneInString(p.str[p.offset:])
|
||||||
if chr == utf8.RuneError && width == 1 {
|
if chr == utf8.RuneError && width == 1 {
|
||||||
self.error(self.chrOffset, "Invalid UTF-8 character")
|
p.error(p.chrOffset, "Invalid UTF-8 character")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.offset += width
|
p.offset += width
|
||||||
self.chr = chr
|
p.chr = chr
|
||||||
} else {
|
} else {
|
||||||
self.chrOffset = self.length
|
p.chrOffset = p.length
|
||||||
self.chr = -1 // EOF
|
p.chr = -1 // EOF
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_parser) readSingleLineComment() (result []rune) {
|
func (p *parser) readSingleLineComment() []rune {
|
||||||
for self.chr != -1 {
|
var result []rune
|
||||||
self.read()
|
for p.chr != -1 {
|
||||||
if isLineTerminator(self.chr) {
|
p.read()
|
||||||
return
|
if isLineTerminator(p.chr) {
|
||||||
|
return result
|
||||||
}
|
}
|
||||||
result = append(result, self.chr)
|
result = append(result, p.chr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get rid of the trailing -1
|
// Get rid of the trailing -1
|
||||||
result = result[:len(result)-1]
|
return result[:len(result)-1]
|
||||||
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_parser) readMultiLineComment() (result []rune) {
|
func (p *parser) readMultiLineComment() []rune {
|
||||||
self.read()
|
var result []rune
|
||||||
for self.chr >= 0 {
|
p.read()
|
||||||
chr := self.chr
|
for p.chr >= 0 {
|
||||||
self.read()
|
chr := p.chr
|
||||||
if chr == '*' && self.chr == '/' {
|
p.read()
|
||||||
self.read()
|
if chr == '*' && p.chr == '/' {
|
||||||
return
|
p.read()
|
||||||
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
result = append(result, chr)
|
result = append(result, chr)
|
||||||
}
|
}
|
||||||
|
|
||||||
self.errorUnexpected(0, self.chr)
|
p.errorUnexpected(0, p.chr)
|
||||||
|
|
||||||
return
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_parser) skipSingleLineComment() {
|
func (p *parser) skipSingleLineComment() {
|
||||||
for self.chr != -1 {
|
for p.chr != -1 {
|
||||||
self.read()
|
p.read()
|
||||||
if isLineTerminator(self.chr) {
|
if isLineTerminator(p.chr) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_parser) skipMultiLineComment() {
|
func (p *parser) skipMultiLineComment() {
|
||||||
self.read()
|
p.read()
|
||||||
for self.chr >= 0 {
|
for p.chr >= 0 {
|
||||||
chr := self.chr
|
chr := p.chr
|
||||||
self.read()
|
p.read()
|
||||||
if chr == '*' && self.chr == '/' {
|
if chr == '*' && p.chr == '/' {
|
||||||
self.read()
|
p.read()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.errorUnexpected(0, self.chr)
|
p.errorUnexpected(0, p.chr)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_parser) skipWhiteSpace() {
|
func (p *parser) skipWhiteSpace() {
|
||||||
for {
|
for {
|
||||||
switch self.chr {
|
switch p.chr {
|
||||||
case ' ', '\t', '\f', '\v', '\u00a0', '\ufeff':
|
case ' ', '\t', '\f', '\v', '\u00a0', '\ufeff':
|
||||||
self.read()
|
p.read()
|
||||||
continue
|
continue
|
||||||
case '\r':
|
case '\r':
|
||||||
if self._peek() == '\n' {
|
if p.peek() == '\n' {
|
||||||
self.comments.AtLineBreak()
|
p.comments.AtLineBreak()
|
||||||
self.read()
|
p.read()
|
||||||
}
|
}
|
||||||
fallthrough
|
fallthrough
|
||||||
case '\u2028', '\u2029', '\n':
|
case '\u2028', '\u2029', '\n':
|
||||||
if self.insertSemicolon {
|
if p.insertSemicolon {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
self.comments.AtLineBreak()
|
p.comments.AtLineBreak()
|
||||||
self.read()
|
p.read()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if self.chr >= utf8.RuneSelf {
|
if p.chr >= utf8.RuneSelf {
|
||||||
if unicode.IsSpace(self.chr) {
|
if unicode.IsSpace(p.chr) {
|
||||||
self.read()
|
p.read()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -506,121 +504,114 @@ func (self *_parser) skipWhiteSpace() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_parser) skipLineWhiteSpace() {
|
func (p *parser) scanMantissa(base int) {
|
||||||
for isLineWhiteSpace(self.chr) {
|
for digitValue(p.chr) < base {
|
||||||
self.read()
|
p.read()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_parser) scanMantissa(base int) {
|
func (p *parser) scanEscape(quote rune) {
|
||||||
for digitValue(self.chr) < base {
|
|
||||||
self.read()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *_parser) scanEscape(quote rune) {
|
|
||||||
var length, base uint32
|
var length, base uint32
|
||||||
switch self.chr {
|
switch p.chr {
|
||||||
//case '0', '1', '2', '3', '4', '5', '6', '7':
|
|
||||||
// Octal:
|
// Octal:
|
||||||
// length, base, limit = 3, 8, 255
|
// length, base, limit = 3, 8, 255
|
||||||
case 'a', 'b', 'f', 'n', 'r', 't', 'v', '\\', '"', '\'', '0':
|
case 'a', 'b', 'f', 'n', 'r', 't', 'v', '\\', '"', '\'', '0':
|
||||||
self.read()
|
p.read()
|
||||||
return
|
return
|
||||||
case '\r', '\n', '\u2028', '\u2029':
|
case '\r', '\n', '\u2028', '\u2029':
|
||||||
self.scanNewline()
|
p.scanNewline()
|
||||||
return
|
return
|
||||||
case 'x':
|
case 'x':
|
||||||
self.read()
|
p.read()
|
||||||
length, base = 2, 16
|
length, base = 2, 16
|
||||||
case 'u':
|
case 'u':
|
||||||
self.read()
|
p.read()
|
||||||
length, base = 4, 16
|
length, base = 4, 16
|
||||||
default:
|
default:
|
||||||
self.read() // Always make progress
|
p.read() // Always make progress
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var value uint32
|
var value uint32
|
||||||
for ; length > 0 && self.chr != quote && self.chr >= 0; length-- {
|
for ; length > 0 && p.chr != quote && p.chr >= 0; length-- {
|
||||||
digit := uint32(digitValue(self.chr))
|
digit := uint32(digitValue(p.chr))
|
||||||
if digit >= base {
|
if digit >= base {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
value = value*base + digit
|
value = value*base + digit
|
||||||
self.read()
|
p.read()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_parser) scanString(offset int) (string, error) {
|
func (p *parser) scanString(offset int) (string, error) {
|
||||||
// " ' /
|
// " ' /
|
||||||
quote := rune(self.str[offset])
|
quote := rune(p.str[offset])
|
||||||
|
|
||||||
for self.chr != quote {
|
for p.chr != quote {
|
||||||
chr := self.chr
|
chr := p.chr
|
||||||
if chr == '\n' || chr == '\r' || chr == '\u2028' || chr == '\u2029' || chr < 0 {
|
if chr == '\n' || chr == '\r' || chr == '\u2028' || chr == '\u2029' || chr < 0 {
|
||||||
goto newline
|
goto newline
|
||||||
}
|
}
|
||||||
self.read()
|
p.read()
|
||||||
if chr == '\\' {
|
switch {
|
||||||
|
case chr == '\\':
|
||||||
if quote == '/' {
|
if quote == '/' {
|
||||||
if self.chr == '\n' || self.chr == '\r' || self.chr == '\u2028' || self.chr == '\u2029' || self.chr < 0 {
|
if p.chr == '\n' || p.chr == '\r' || p.chr == '\u2028' || p.chr == '\u2029' || p.chr < 0 {
|
||||||
goto newline
|
goto newline
|
||||||
}
|
}
|
||||||
self.read()
|
p.read()
|
||||||
} else {
|
} else {
|
||||||
self.scanEscape(quote)
|
p.scanEscape(quote)
|
||||||
}
|
}
|
||||||
} else if chr == '[' && quote == '/' {
|
case chr == '[' && quote == '/':
|
||||||
// Allow a slash (/) in a bracket character class ([...])
|
// Allow a slash (/) in a bracket character class ([...])
|
||||||
// TODO Fix this, this is hacky...
|
// TODO Fix this, this is hacky...
|
||||||
quote = -1
|
quote = -1
|
||||||
} else if chr == ']' && quote == -1 {
|
case chr == ']' && quote == -1:
|
||||||
quote = '/'
|
quote = '/'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// " ' /
|
// " ' /
|
||||||
self.read()
|
p.read()
|
||||||
|
|
||||||
return string(self.str[offset:self.chrOffset]), nil
|
return p.str[offset:p.chrOffset], nil
|
||||||
|
|
||||||
newline:
|
newline:
|
||||||
self.scanNewline()
|
p.scanNewline()
|
||||||
err := "String not terminated"
|
err := "String not terminated"
|
||||||
if quote == '/' {
|
if quote == '/' {
|
||||||
err = "Invalid regular expression: missing /"
|
err = "Invalid regular expression: missing /"
|
||||||
self.error(self.idxOf(offset), err)
|
p.error(p.idxOf(offset), err)
|
||||||
}
|
}
|
||||||
return "", errors.New(err)
|
return "", errors.New(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_parser) scanNewline() {
|
func (p *parser) scanNewline() {
|
||||||
if self.chr == '\r' {
|
if p.chr == '\r' {
|
||||||
self.read()
|
p.read()
|
||||||
if self.chr != '\n' {
|
if p.chr != '\n' {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.read()
|
p.read()
|
||||||
}
|
}
|
||||||
|
|
||||||
func hex2decimal(chr byte) (value rune, ok bool) {
|
func hex2decimal(chr byte) (rune, bool) {
|
||||||
{
|
r := rune(chr)
|
||||||
chr := rune(chr)
|
|
||||||
switch {
|
switch {
|
||||||
case '0' <= chr && chr <= '9':
|
case '0' <= r && r <= '9':
|
||||||
return chr - '0', true
|
return r - '0', true
|
||||||
case 'a' <= chr && chr <= 'f':
|
case 'a' <= r && r <= 'f':
|
||||||
return chr - 'a' + 10, true
|
return r - 'a' + 10, true
|
||||||
case 'A' <= chr && chr <= 'F':
|
case 'A' <= r && r <= 'F':
|
||||||
return chr - 'A' + 10, true
|
return r - 'A' + 10, true
|
||||||
}
|
default:
|
||||||
return
|
return 0, false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseNumberLiteral(literal string) (value interface{}, err error) {
|
func parseNumberLiteral(literal string) (value interface{}, err error) { //nolint: nonamedreturns
|
||||||
// TODO Is Uint okay? What about -MAX_UINT
|
// TODO Is Uint okay? What about -MAX_UINT
|
||||||
value, err = strconv.ParseInt(literal, 0, 64)
|
value, err = strconv.ParseInt(literal, 0, 64)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
@ -632,14 +623,16 @@ func parseNumberLiteral(literal string) (value interface{}, err error) {
|
||||||
value, err = strconv.ParseFloat(literal, 64)
|
value, err = strconv.ParseFloat(literal, 64)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return value, nil
|
return value, nil
|
||||||
} else if err.(*strconv.NumError).Err == strconv.ErrRange {
|
} else if errors.Is(err, strconv.ErrRange) {
|
||||||
// Infinity, etc.
|
// Infinity, etc.
|
||||||
return value, nil
|
return value, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(steve): Fix as this is assigning to err so we know the type.
|
||||||
|
// Need to understand what this was trying to do?
|
||||||
err = parseIntErr
|
err = parseIntErr
|
||||||
|
|
||||||
if err.(*strconv.NumError).Err == strconv.ErrRange {
|
if errors.Is(err, strconv.ErrRange) {
|
||||||
if len(literal) > 2 && literal[0] == '0' && (literal[1] == 'X' || literal[1] == 'x') {
|
if len(literal) > 2 && literal[0] == '0' && (literal[1] == 'X' || literal[1] == 'x') {
|
||||||
// Could just be a very large number (e.g. 0x8000000000000000)
|
// Could just be a very large number (e.g. 0x8000000000000000)
|
||||||
var value float64
|
var value float64
|
||||||
|
@ -647,7 +640,7 @@ func parseNumberLiteral(literal string) (value interface{}, err error) {
|
||||||
for _, chr := range literal {
|
for _, chr := range literal {
|
||||||
digit := digitValue(chr)
|
digit := digitValue(chr)
|
||||||
if digit >= 16 {
|
if digit >= 16 {
|
||||||
return nil, errors.New("Illegal numeric literal")
|
return nil, fmt.Errorf("illegal numeric literal: %v (>= 16)", digit)
|
||||||
}
|
}
|
||||||
value = value*16 + float64(digit)
|
value = value*16 + float64(digit)
|
||||||
}
|
}
|
||||||
|
@ -655,7 +648,7 @@ func parseNumberLiteral(literal string) (value interface{}, err error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, errors.New("Illegal numeric literal")
|
return nil, errors.New("illegal numeric literal")
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseStringLiteral(literal string) (string, error) {
|
func parseStringLiteral(literal string) (string, error) {
|
||||||
|
@ -783,78 +776,79 @@ func parseStringLiteral(literal string) (string, error) {
|
||||||
return buffer.String(), nil
|
return buffer.String(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_parser) scanNumericLiteral(decimalPoint bool) (token.Token, string) {
|
func (p *parser) scanNumericLiteral(decimalPoint bool) (token.Token, string) {
|
||||||
offset := self.chrOffset
|
offset := p.chrOffset
|
||||||
tkn := token.NUMBER
|
tkn := token.NUMBER
|
||||||
|
|
||||||
if decimalPoint {
|
if decimalPoint {
|
||||||
offset--
|
offset--
|
||||||
self.scanMantissa(10)
|
p.scanMantissa(10)
|
||||||
goto exponent
|
goto exponent
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.chr == '0' {
|
if p.chr == '0' {
|
||||||
offset := self.chrOffset
|
offset := p.chrOffset
|
||||||
self.read()
|
p.read()
|
||||||
if self.chr == 'x' || self.chr == 'X' {
|
switch p.chr {
|
||||||
|
case 'x', 'X':
|
||||||
// Hexadecimal
|
// Hexadecimal
|
||||||
self.read()
|
p.read()
|
||||||
if isDigit(self.chr, 16) {
|
if isDigit(p.chr, 16) {
|
||||||
self.read()
|
p.read()
|
||||||
} else {
|
} else {
|
||||||
return token.ILLEGAL, self.str[offset:self.chrOffset]
|
return token.ILLEGAL, p.str[offset:p.chrOffset]
|
||||||
}
|
}
|
||||||
self.scanMantissa(16)
|
p.scanMantissa(16)
|
||||||
|
|
||||||
if self.chrOffset-offset <= 2 {
|
if p.chrOffset-offset <= 2 {
|
||||||
// Only "0x" or "0X"
|
// Only "0x" or "0X"
|
||||||
self.error(0, "Illegal hexadecimal number")
|
p.error(0, "Illegal hexadecimal number")
|
||||||
}
|
}
|
||||||
|
|
||||||
goto hexadecimal
|
goto hexadecimal
|
||||||
} else if self.chr == '.' {
|
case '.':
|
||||||
// Float
|
// Float
|
||||||
goto float
|
goto float
|
||||||
} else {
|
default:
|
||||||
// Octal, Float
|
// Octal, Float
|
||||||
if self.chr == 'e' || self.chr == 'E' {
|
if p.chr == 'e' || p.chr == 'E' {
|
||||||
goto exponent
|
goto exponent
|
||||||
}
|
}
|
||||||
self.scanMantissa(8)
|
p.scanMantissa(8)
|
||||||
if self.chr == '8' || self.chr == '9' {
|
if p.chr == '8' || p.chr == '9' {
|
||||||
return token.ILLEGAL, self.str[offset:self.chrOffset]
|
return token.ILLEGAL, p.str[offset:p.chrOffset]
|
||||||
}
|
}
|
||||||
goto octal
|
goto octal
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.scanMantissa(10)
|
p.scanMantissa(10)
|
||||||
|
|
||||||
float:
|
float:
|
||||||
if self.chr == '.' {
|
if p.chr == '.' {
|
||||||
self.read()
|
p.read()
|
||||||
self.scanMantissa(10)
|
p.scanMantissa(10)
|
||||||
}
|
}
|
||||||
|
|
||||||
exponent:
|
exponent:
|
||||||
if self.chr == 'e' || self.chr == 'E' {
|
if p.chr == 'e' || p.chr == 'E' {
|
||||||
self.read()
|
p.read()
|
||||||
if self.chr == '-' || self.chr == '+' {
|
if p.chr == '-' || p.chr == '+' {
|
||||||
self.read()
|
p.read()
|
||||||
}
|
}
|
||||||
if isDecimalDigit(self.chr) {
|
if isDecimalDigit(p.chr) {
|
||||||
self.read()
|
p.read()
|
||||||
self.scanMantissa(10)
|
p.scanMantissa(10)
|
||||||
} else {
|
} else {
|
||||||
return token.ILLEGAL, self.str[offset:self.chrOffset]
|
return token.ILLEGAL, p.str[offset:p.chrOffset]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hexadecimal:
|
hexadecimal:
|
||||||
octal:
|
octal:
|
||||||
if isIdentifierStart(self.chr) || isDecimalDigit(self.chr) {
|
if isIdentifierStart(p.chr) || isDecimalDigit(p.chr) {
|
||||||
return token.ILLEGAL, self.str[offset:self.chrOffset]
|
return token.ILLEGAL, p.str[offset:p.chrOffset]
|
||||||
}
|
}
|
||||||
|
|
||||||
return tkn, self.str[offset:self.chrOffset]
|
return tkn, p.str[offset:p.chrOffset]
|
||||||
}
|
}
|
||||||
|
|
136
v1/vendor/github.com/robertkrimen/otto/parser/parser.go
generated
vendored
|
@ -35,9 +35,9 @@ package parser
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"errors"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"os"
|
||||||
|
|
||||||
"github.com/robertkrimen/otto/ast"
|
"github.com/robertkrimen/otto/ast"
|
||||||
"github.com/robertkrimen/otto/file"
|
"github.com/robertkrimen/otto/file"
|
||||||
|
@ -49,11 +49,14 @@ import (
|
||||||
type Mode uint
|
type Mode uint
|
||||||
|
|
||||||
const (
|
const (
|
||||||
IgnoreRegExpErrors Mode = 1 << iota // Ignore RegExp compatibility errors (allow backtracking)
|
// IgnoreRegExpErrors ignores RegExp compatibility errors (allow backtracking).
|
||||||
StoreComments // Store the comments from source to the comments map
|
IgnoreRegExpErrors Mode = 1 << iota
|
||||||
|
|
||||||
|
// StoreComments stores the comments from source to the comments map.
|
||||||
|
StoreComments
|
||||||
)
|
)
|
||||||
|
|
||||||
type _parser struct {
|
type parser struct { //nolint: maligned
|
||||||
str string
|
str string
|
||||||
length int
|
length int
|
||||||
base int
|
base int
|
||||||
|
@ -66,7 +69,7 @@ type _parser struct {
|
||||||
token token.Token // The token
|
token token.Token // The token
|
||||||
literal string // The literal of the token, if any
|
literal string // The literal of the token, if any
|
||||||
|
|
||||||
scope *_scope
|
scope *scope
|
||||||
insertSemicolon bool // If we see a newline, then insert an implicit semicolon
|
insertSemicolon bool // If we see a newline, then insert an implicit semicolon
|
||||||
implicitSemicolon bool // An implicit semicolon exists
|
implicitSemicolon bool // An implicit semicolon exists
|
||||||
|
|
||||||
|
@ -85,12 +88,13 @@ type _parser struct {
|
||||||
comments *ast.Comments
|
comments *ast.Comments
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Parser is implemented by types which can parse JavaScript Code.
|
||||||
type Parser interface {
|
type Parser interface {
|
||||||
Scan() (tkn token.Token, literal string, idx file.Idx)
|
Scan() (tkn token.Token, literal string, idx file.Idx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func _newParser(filename, src string, base int, sm *sourcemap.Consumer) *_parser {
|
func newParser(filename, src string, base int, sm *sourcemap.Consumer) *parser {
|
||||||
return &_parser{
|
return &parser{
|
||||||
chr: ' ', // This is set so we can start scanning by skipping whitespace
|
chr: ' ', // This is set so we can start scanning by skipping whitespace
|
||||||
str: src,
|
str: src,
|
||||||
length: len(src),
|
length: len(src),
|
||||||
|
@ -100,11 +104,12 @@ func _newParser(filename, src string, base int, sm *sourcemap.Consumer) *_parser
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns a new Parser.
|
// NewParser returns a new Parser.
|
||||||
func NewParser(filename, src string) Parser {
|
func NewParser(filename, src string) Parser {
|
||||||
return _newParser(filename, src, 1, nil)
|
return newParser(filename, src, 1, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReadSource reads code from src if not nil, otherwise reads from filename.
|
||||||
func ReadSource(filename string, src interface{}) ([]byte, error) {
|
func ReadSource(filename string, src interface{}) ([]byte, error) {
|
||||||
if src != nil {
|
if src != nil {
|
||||||
switch src := src.(type) {
|
switch src := src.(type) {
|
||||||
|
@ -122,12 +127,14 @@ func ReadSource(filename string, src interface{}) ([]byte, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return bfr.Bytes(), nil
|
return bfr.Bytes(), nil
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("invalid src type %T", src)
|
||||||
}
|
}
|
||||||
return nil, errors.New("invalid source")
|
|
||||||
}
|
}
|
||||||
return ioutil.ReadFile(filename)
|
return os.ReadFile(filename) //nolint: gosec
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReadSourceMap reads the source map from src if not nil, otherwise is a noop.
|
||||||
func ReadSourceMap(filename string, src interface{}) (*sourcemap.Consumer, error) {
|
func ReadSourceMap(filename string, src interface{}) (*sourcemap.Consumer, error) {
|
||||||
if src == nil {
|
if src == nil {
|
||||||
return nil, nil //nolint: nilnil
|
return nil, nil //nolint: nilnil
|
||||||
|
@ -139,9 +146,7 @@ func ReadSourceMap(filename string, src interface{}) (*sourcemap.Consumer, error
|
||||||
case []byte:
|
case []byte:
|
||||||
return sourcemap.Parse(filename, src)
|
return sourcemap.Parse(filename, src)
|
||||||
case *bytes.Buffer:
|
case *bytes.Buffer:
|
||||||
if src != nil {
|
|
||||||
return sourcemap.Parse(filename, src.Bytes())
|
return sourcemap.Parse(filename, src.Bytes())
|
||||||
}
|
|
||||||
case io.Reader:
|
case io.Reader:
|
||||||
var bfr bytes.Buffer
|
var bfr bytes.Buffer
|
||||||
if _, err := io.Copy(&bfr, src); err != nil {
|
if _, err := io.Copy(&bfr, src); err != nil {
|
||||||
|
@ -150,11 +155,12 @@ func ReadSourceMap(filename string, src interface{}) (*sourcemap.Consumer, error
|
||||||
return sourcemap.Parse(filename, bfr.Bytes())
|
return sourcemap.Parse(filename, bfr.Bytes())
|
||||||
case *sourcemap.Consumer:
|
case *sourcemap.Consumer:
|
||||||
return src, nil
|
return src, nil
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("invalid sourcemap type %T", src)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, errors.New("invalid sourcemap type")
|
// ParseFileWithSourceMap parses the sourcemap returning the resulting Program.
|
||||||
}
|
|
||||||
|
|
||||||
func ParseFileWithSourceMap(fileSet *file.FileSet, filename string, javascriptSource, sourcemapSource interface{}, mode Mode) (*ast.Program, error) {
|
func ParseFileWithSourceMap(fileSet *file.FileSet, filename string, javascriptSource, sourcemapSource interface{}, mode Mode) (*ast.Program, error) {
|
||||||
src, err := ReadSource(filename, javascriptSource)
|
src, err := ReadSource(filename, javascriptSource)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -184,10 +190,10 @@ func ParseFileWithSourceMap(fileSet *file.FileSet, filename string, javascriptSo
|
||||||
base = fileSet.AddFile(filename, string(src))
|
base = fileSet.AddFile(filename, string(src))
|
||||||
}
|
}
|
||||||
|
|
||||||
parser := _newParser(filename, string(src), base, sm)
|
p := newParser(filename, string(src), base, sm)
|
||||||
parser.mode = mode
|
p.mode = mode
|
||||||
program, err := parser.parse()
|
program, err := p.parse()
|
||||||
program.Comments = parser.comments.CommentMap
|
program.Comments = p.comments.CommentMap
|
||||||
|
|
||||||
return program, err
|
return program, err
|
||||||
}
|
}
|
||||||
|
@ -215,8 +221,8 @@ func ParseFile(fileSet *file.FileSet, filename string, src interface{}, mode Mod
|
||||||
func ParseFunction(parameterList, body string) (*ast.FunctionLiteral, error) {
|
func ParseFunction(parameterList, body string) (*ast.FunctionLiteral, error) {
|
||||||
src := "(function(" + parameterList + ") {\n" + body + "\n})"
|
src := "(function(" + parameterList + ") {\n" + body + "\n})"
|
||||||
|
|
||||||
parser := _newParser("", src, 1, nil)
|
p := newParser("", src, 1, nil)
|
||||||
program, err := parser.parse()
|
program, err := p.parse()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -227,75 +233,75 @@ func ParseFunction(parameterList, body string) (*ast.FunctionLiteral, error) {
|
||||||
// Scan reads a single token from the source at the current offset, increments the offset and
|
// Scan reads a single token from the source at the current offset, increments the offset and
|
||||||
// returns the token.Token token, a string literal representing the value of the token (if applicable)
|
// returns the token.Token token, a string literal representing the value of the token (if applicable)
|
||||||
// and it's current file.Idx index.
|
// and it's current file.Idx index.
|
||||||
func (self *_parser) Scan() (tkn token.Token, literal string, idx file.Idx) {
|
func (p *parser) Scan() (token.Token, string, file.Idx) {
|
||||||
return self.scan()
|
return p.scan()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_parser) slice(idx0, idx1 file.Idx) string {
|
func (p *parser) slice(idx0, idx1 file.Idx) string {
|
||||||
from := int(idx0) - self.base
|
from := int(idx0) - p.base
|
||||||
to := int(idx1) - self.base
|
to := int(idx1) - p.base
|
||||||
if from >= 0 && to <= len(self.str) {
|
if from >= 0 && to <= len(p.str) {
|
||||||
return self.str[from:to]
|
return p.str[from:to]
|
||||||
}
|
}
|
||||||
|
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_parser) parse() (*ast.Program, error) {
|
func (p *parser) parse() (*ast.Program, error) {
|
||||||
self.next()
|
p.next()
|
||||||
program := self.parseProgram()
|
program := p.parseProgram()
|
||||||
if false {
|
if false {
|
||||||
self.errors.Sort()
|
p.errors.Sort()
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.mode&StoreComments != 0 {
|
if p.mode&StoreComments != 0 {
|
||||||
self.comments.CommentMap.AddComments(program, self.comments.FetchAll(), ast.TRAILING)
|
p.comments.CommentMap.AddComments(program, p.comments.FetchAll(), ast.TRAILING)
|
||||||
}
|
}
|
||||||
|
|
||||||
return program, self.errors.Err()
|
return program, p.errors.Err()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_parser) next() {
|
func (p *parser) next() {
|
||||||
self.token, self.literal, self.idx = self.scan()
|
p.token, p.literal, p.idx = p.scan()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_parser) optionalSemicolon() {
|
func (p *parser) optionalSemicolon() {
|
||||||
if self.token == token.SEMICOLON {
|
if p.token == token.SEMICOLON {
|
||||||
self.next()
|
p.next()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.implicitSemicolon {
|
if p.implicitSemicolon {
|
||||||
self.implicitSemicolon = false
|
p.implicitSemicolon = false
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.token != token.EOF && self.token != token.RIGHT_BRACE {
|
if p.token != token.EOF && p.token != token.RIGHT_BRACE {
|
||||||
self.expect(token.SEMICOLON)
|
p.expect(token.SEMICOLON)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_parser) semicolon() {
|
func (p *parser) semicolon() {
|
||||||
if self.token != token.RIGHT_PARENTHESIS && self.token != token.RIGHT_BRACE {
|
if p.token != token.RIGHT_PARENTHESIS && p.token != token.RIGHT_BRACE {
|
||||||
if self.implicitSemicolon {
|
if p.implicitSemicolon {
|
||||||
self.implicitSemicolon = false
|
p.implicitSemicolon = false
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
self.expect(token.SEMICOLON)
|
p.expect(token.SEMICOLON)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_parser) idxOf(offset int) file.Idx {
|
func (p *parser) idxOf(offset int) file.Idx {
|
||||||
return file.Idx(self.base + offset)
|
return file.Idx(p.base + offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_parser) expect(value token.Token) file.Idx {
|
func (p *parser) expect(value token.Token) file.Idx {
|
||||||
idx := self.idx
|
idx := p.idx
|
||||||
if self.token != value {
|
if p.token != value {
|
||||||
self.errorUnexpectedToken(self.token)
|
p.errorUnexpectedToken(p.token)
|
||||||
}
|
}
|
||||||
self.next()
|
p.next()
|
||||||
return idx
|
return idx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -305,17 +311,17 @@ func lineCount(str string) (int, int) {
|
||||||
for index, chr := range str {
|
for index, chr := range str {
|
||||||
switch chr {
|
switch chr {
|
||||||
case '\r':
|
case '\r':
|
||||||
line += 1
|
line++
|
||||||
last = index
|
last = index
|
||||||
pair = true
|
pair = true
|
||||||
continue
|
continue
|
||||||
case '\n':
|
case '\n':
|
||||||
if !pair {
|
if !pair {
|
||||||
line += 1
|
line++
|
||||||
}
|
}
|
||||||
last = index
|
last = index
|
||||||
case '\u2028', '\u2029':
|
case '\u2028', '\u2029':
|
||||||
line += 1
|
line++
|
||||||
last = index + 2
|
last = index + 2
|
||||||
}
|
}
|
||||||
pair = false
|
pair = false
|
||||||
|
@ -323,11 +329,11 @@ func lineCount(str string) (int, int) {
|
||||||
return line, last
|
return line, last
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_parser) position(idx file.Idx) file.Position {
|
func (p *parser) position(idx file.Idx) file.Position {
|
||||||
position := file.Position{}
|
position := file.Position{}
|
||||||
offset := int(idx) - self.base
|
offset := int(idx) - p.base
|
||||||
str := self.str[:offset]
|
str := p.str[:offset]
|
||||||
position.Filename = self.file.Name()
|
position.Filename = p.file.Name()
|
||||||
line, last := lineCount(str)
|
line, last := lineCount(str)
|
||||||
position.Line = 1 + line
|
position.Line = 1 + line
|
||||||
if last >= 0 {
|
if last >= 0 {
|
||||||
|
|
250
v1/vendor/github.com/robertkrimen/otto/parser/regexp.go
generated
vendored
|
@ -6,7 +6,7 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
type _RegExp_parser struct {
|
type regExpParser struct { //nolint: maligned
|
||||||
str string
|
str string
|
||||||
length int
|
length int
|
||||||
|
|
||||||
|
@ -40,128 +40,128 @@ func TransformRegExp(pattern string) (string, error) {
|
||||||
|
|
||||||
// TODO If without \, if without (?=, (?!, then another shortcut
|
// TODO If without \, if without (?=, (?!, then another shortcut
|
||||||
|
|
||||||
parser := _RegExp_parser{
|
p := regExpParser{
|
||||||
str: pattern,
|
str: pattern,
|
||||||
length: len(pattern),
|
length: len(pattern),
|
||||||
goRegexp: bytes.NewBuffer(make([]byte, 0, 3*len(pattern)/2)),
|
goRegexp: bytes.NewBuffer(make([]byte, 0, 3*len(pattern)/2)),
|
||||||
}
|
}
|
||||||
parser.read() // Pull in the first character
|
p.read() // Pull in the first character
|
||||||
parser.scan()
|
p.scan()
|
||||||
var err error
|
var err error
|
||||||
if len(parser.errors) > 0 {
|
if len(p.errors) > 0 {
|
||||||
err = parser.errors[0]
|
err = p.errors[0]
|
||||||
}
|
}
|
||||||
if parser.invalid {
|
if p.invalid {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Might not be re2 compatible, but is still a valid JavaScript RegExp
|
// Might not be re2 compatible, but is still a valid JavaScript RegExp
|
||||||
return parser.goRegexp.String(), err
|
return p.goRegexp.String(), err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_RegExp_parser) scan() {
|
func (p *regExpParser) scan() {
|
||||||
for self.chr != -1 {
|
for p.chr != -1 {
|
||||||
switch self.chr {
|
switch p.chr {
|
||||||
case '\\':
|
case '\\':
|
||||||
self.read()
|
p.read()
|
||||||
self.scanEscape(false)
|
p.scanEscape(false)
|
||||||
case '(':
|
case '(':
|
||||||
self.pass()
|
p.pass()
|
||||||
self.scanGroup()
|
p.scanGroup()
|
||||||
case '[':
|
case '[':
|
||||||
self.pass()
|
p.pass()
|
||||||
self.scanBracket()
|
p.scanBracket()
|
||||||
case ')':
|
case ')':
|
||||||
self.error(-1, "Unmatched ')'")
|
p.error(-1, "Unmatched ')'")
|
||||||
self.invalid = true
|
p.invalid = true
|
||||||
self.pass()
|
p.pass()
|
||||||
default:
|
default:
|
||||||
self.pass()
|
p.pass()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// (...)
|
// (...)
|
||||||
func (self *_RegExp_parser) scanGroup() {
|
func (p *regExpParser) scanGroup() {
|
||||||
str := self.str[self.chrOffset:]
|
str := p.str[p.chrOffset:]
|
||||||
if len(str) > 1 { // A possibility of (?= or (?!
|
if len(str) > 1 { // A possibility of (?= or (?!
|
||||||
if str[0] == '?' {
|
if str[0] == '?' {
|
||||||
if str[1] == '=' || str[1] == '!' {
|
if str[1] == '=' || str[1] == '!' {
|
||||||
self.error(-1, "re2: Invalid (%s) <lookahead>", self.str[self.chrOffset:self.chrOffset+2])
|
p.error(-1, "re2: Invalid (%s) <lookahead>", p.str[p.chrOffset:p.chrOffset+2])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for self.chr != -1 && self.chr != ')' {
|
for p.chr != -1 && p.chr != ')' {
|
||||||
switch self.chr {
|
switch p.chr {
|
||||||
case '\\':
|
case '\\':
|
||||||
self.read()
|
p.read()
|
||||||
self.scanEscape(false)
|
p.scanEscape(false)
|
||||||
case '(':
|
case '(':
|
||||||
self.pass()
|
p.pass()
|
||||||
self.scanGroup()
|
p.scanGroup()
|
||||||
case '[':
|
case '[':
|
||||||
self.pass()
|
p.pass()
|
||||||
self.scanBracket()
|
p.scanBracket()
|
||||||
default:
|
default:
|
||||||
self.pass()
|
p.pass()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if self.chr != ')' {
|
if p.chr != ')' {
|
||||||
self.error(-1, "Unterminated group")
|
p.error(-1, "Unterminated group")
|
||||||
self.invalid = true
|
p.invalid = true
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
self.pass()
|
p.pass()
|
||||||
}
|
}
|
||||||
|
|
||||||
// [...]
|
// [...].
|
||||||
func (self *_RegExp_parser) scanBracket() {
|
func (p *regExpParser) scanBracket() {
|
||||||
for self.chr != -1 {
|
for p.chr != -1 {
|
||||||
if self.chr == ']' {
|
if p.chr == ']' {
|
||||||
break
|
break
|
||||||
} else if self.chr == '\\' {
|
} else if p.chr == '\\' {
|
||||||
self.read()
|
p.read()
|
||||||
self.scanEscape(true)
|
p.scanEscape(true)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
self.pass()
|
p.pass()
|
||||||
}
|
}
|
||||||
if self.chr != ']' {
|
if p.chr != ']' {
|
||||||
self.error(-1, "Unterminated character class")
|
p.error(-1, "Unterminated character class")
|
||||||
self.invalid = true
|
p.invalid = true
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
self.pass()
|
p.pass()
|
||||||
}
|
}
|
||||||
|
|
||||||
// \...
|
// \...
|
||||||
func (self *_RegExp_parser) scanEscape(inClass bool) {
|
func (p *regExpParser) scanEscape(inClass bool) {
|
||||||
offset := self.chrOffset
|
offset := p.chrOffset
|
||||||
|
|
||||||
var length, base uint32
|
var length, base uint32
|
||||||
switch self.chr {
|
switch p.chr {
|
||||||
case '0', '1', '2', '3', '4', '5', '6', '7':
|
case '0', '1', '2', '3', '4', '5', '6', '7':
|
||||||
var value int64
|
var value int64
|
||||||
size := 0
|
size := 0
|
||||||
for {
|
for {
|
||||||
digit := int64(digitValue(self.chr))
|
digit := int64(digitValue(p.chr))
|
||||||
if digit >= 8 {
|
if digit >= 8 {
|
||||||
// Not a valid digit
|
// Not a valid digit
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
value = value*8 + digit
|
value = value*8 + digit
|
||||||
self.read()
|
p.read()
|
||||||
size += 1
|
size++
|
||||||
}
|
}
|
||||||
if size == 1 { // The number of characters read
|
if size == 1 { // The number of characters read
|
||||||
_, err := self.goRegexp.Write([]byte{'\\', byte(value) + '0'})
|
_, err := p.goRegexp.Write([]byte{'\\', byte(value) + '0'})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
self.errors = append(self.errors, err)
|
p.errors = append(p.errors, err)
|
||||||
}
|
}
|
||||||
if value != 0 {
|
if value != 0 {
|
||||||
// An invalid backreference
|
// An invalid backreference
|
||||||
self.error(-1, "re2: Invalid \\%d <backreference>", value)
|
p.error(-1, "re2: Invalid \\%d <backreference>", value)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -172,49 +172,49 @@ func (self *_RegExp_parser) scanEscape(inClass bool) {
|
||||||
tmp = tmp[0:3]
|
tmp = tmp[0:3]
|
||||||
}
|
}
|
||||||
tmp = strconv.AppendInt(tmp, value, 16)
|
tmp = strconv.AppendInt(tmp, value, 16)
|
||||||
_, err := self.goRegexp.Write(tmp)
|
_, err := p.goRegexp.Write(tmp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
self.errors = append(self.errors, err)
|
p.errors = append(p.errors, err)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
|
||||||
case '8', '9':
|
case '8', '9':
|
||||||
size := 0
|
size := 0
|
||||||
for {
|
for {
|
||||||
digit := digitValue(self.chr)
|
digit := digitValue(p.chr)
|
||||||
if digit >= 10 {
|
if digit >= 10 {
|
||||||
// Not a valid digit
|
// Not a valid digit
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
self.read()
|
p.read()
|
||||||
size += 1
|
size++
|
||||||
}
|
}
|
||||||
err := self.goRegexp.WriteByte('\\')
|
err := p.goRegexp.WriteByte('\\')
|
||||||
if err != nil {
|
if err != nil {
|
||||||
self.errors = append(self.errors, err)
|
p.errors = append(p.errors, err)
|
||||||
}
|
}
|
||||||
_, err = self.goRegexp.WriteString(self.str[offset:self.chrOffset])
|
_, err = p.goRegexp.WriteString(p.str[offset:p.chrOffset])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
self.errors = append(self.errors, err)
|
p.errors = append(p.errors, err)
|
||||||
}
|
}
|
||||||
self.error(-1, "re2: Invalid \\%s <backreference>", self.str[offset:self.chrOffset])
|
p.error(-1, "re2: Invalid \\%s <backreference>", p.str[offset:p.chrOffset])
|
||||||
return
|
return
|
||||||
|
|
||||||
case 'x':
|
case 'x':
|
||||||
self.read()
|
p.read()
|
||||||
length, base = 2, 16
|
length, base = 2, 16
|
||||||
|
|
||||||
case 'u':
|
case 'u':
|
||||||
self.read()
|
p.read()
|
||||||
length, base = 4, 16
|
length, base = 4, 16
|
||||||
|
|
||||||
case 'b':
|
case 'b':
|
||||||
if inClass {
|
if inClass {
|
||||||
_, err := self.goRegexp.Write([]byte{'\\', 'x', '0', '8'})
|
_, err := p.goRegexp.Write([]byte{'\\', 'x', '0', '8'})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
self.errors = append(self.errors, err)
|
p.errors = append(p.errors, err)
|
||||||
}
|
}
|
||||||
self.read()
|
p.read()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
fallthrough
|
fallthrough
|
||||||
|
@ -231,24 +231,25 @@ func (self *_RegExp_parser) scanEscape(inClass bool) {
|
||||||
fallthrough
|
fallthrough
|
||||||
|
|
||||||
case 'f', 'n', 'r', 't', 'v':
|
case 'f', 'n', 'r', 't', 'v':
|
||||||
err := self.goRegexp.WriteByte('\\')
|
err := p.goRegexp.WriteByte('\\')
|
||||||
if err != nil {
|
if err != nil {
|
||||||
self.errors = append(self.errors, err)
|
p.errors = append(p.errors, err)
|
||||||
}
|
}
|
||||||
self.pass()
|
p.pass()
|
||||||
return
|
return
|
||||||
|
|
||||||
case 'c':
|
case 'c':
|
||||||
self.read()
|
p.read()
|
||||||
var value int64
|
var value int64
|
||||||
if 'a' <= self.chr && self.chr <= 'z' {
|
switch {
|
||||||
value = int64(self.chr) - 'a' + 1
|
case 'a' <= p.chr && p.chr <= 'z':
|
||||||
} else if 'A' <= self.chr && self.chr <= 'Z' {
|
value = int64(p.chr) - 'a' + 1
|
||||||
value = int64(self.chr) - 'A' + 1
|
case 'A' <= p.chr && p.chr <= 'Z':
|
||||||
} else {
|
value = int64(p.chr) - 'A' + 1
|
||||||
err := self.goRegexp.WriteByte('c')
|
default:
|
||||||
|
err := p.goRegexp.WriteByte('c')
|
||||||
if err != nil {
|
if err != nil {
|
||||||
self.errors = append(self.errors, err)
|
p.errors = append(p.errors, err)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -259,98 +260,93 @@ func (self *_RegExp_parser) scanEscape(inClass bool) {
|
||||||
tmp = tmp[0:3]
|
tmp = tmp[0:3]
|
||||||
}
|
}
|
||||||
tmp = strconv.AppendInt(tmp, value, 16)
|
tmp = strconv.AppendInt(tmp, value, 16)
|
||||||
_, err := self.goRegexp.Write(tmp)
|
_, err := p.goRegexp.Write(tmp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
self.errors = append(self.errors, err)
|
p.errors = append(p.errors, err)
|
||||||
}
|
}
|
||||||
self.read()
|
p.read()
|
||||||
return
|
return
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// $ is an identifier character, so we have to have
|
// $ is an identifier character, so we have to have
|
||||||
// a special case for it here
|
// a special case for it here
|
||||||
if self.chr == '$' || !isIdentifierPart(self.chr) {
|
if p.chr == '$' || !isIdentifierPart(p.chr) {
|
||||||
// A non-identifier character needs escaping
|
// A non-identifier character needs escaping
|
||||||
err := self.goRegexp.WriteByte('\\')
|
err := p.goRegexp.WriteByte('\\')
|
||||||
if err != nil {
|
if err != nil {
|
||||||
self.errors = append(self.errors, err)
|
p.errors = append(p.errors, err)
|
||||||
}
|
}
|
||||||
} else {
|
} else { //nolint: staticcheck
|
||||||
// Unescape the character for re2
|
// Unescape the character for re2
|
||||||
}
|
}
|
||||||
self.pass()
|
p.pass()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, we're a \u.... or \x...
|
// Otherwise, we're a \u.... or \x...
|
||||||
valueOffset := self.chrOffset
|
valueOffset := p.chrOffset
|
||||||
|
|
||||||
var value uint32
|
var value uint32
|
||||||
{
|
for length := length; length > 0; length-- {
|
||||||
length := length
|
digit := uint32(digitValue(p.chr))
|
||||||
for ; length > 0; length-- {
|
|
||||||
digit := uint32(digitValue(self.chr))
|
|
||||||
if digit >= base {
|
if digit >= base {
|
||||||
// Not a valid digit
|
// Not a valid digit
|
||||||
goto skip
|
goto skip
|
||||||
}
|
}
|
||||||
value = value*base + digit
|
value = value*base + digit
|
||||||
self.read()
|
p.read()
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if length == 4 {
|
switch length {
|
||||||
_, err := self.goRegexp.Write([]byte{
|
case 4:
|
||||||
|
if _, err := p.goRegexp.Write([]byte{
|
||||||
'\\',
|
'\\',
|
||||||
'x',
|
'x',
|
||||||
'{',
|
'{',
|
||||||
self.str[valueOffset+0],
|
p.str[valueOffset+0],
|
||||||
self.str[valueOffset+1],
|
p.str[valueOffset+1],
|
||||||
self.str[valueOffset+2],
|
p.str[valueOffset+2],
|
||||||
self.str[valueOffset+3],
|
p.str[valueOffset+3],
|
||||||
'}',
|
'}',
|
||||||
})
|
}); err != nil {
|
||||||
if err != nil {
|
p.errors = append(p.errors, err)
|
||||||
self.errors = append(self.errors, err)
|
|
||||||
}
|
}
|
||||||
} else if length == 2 {
|
case 2:
|
||||||
_, err := self.goRegexp.Write([]byte{
|
if _, err := p.goRegexp.Write([]byte{
|
||||||
'\\',
|
'\\',
|
||||||
'x',
|
'x',
|
||||||
self.str[valueOffset+0],
|
p.str[valueOffset+0],
|
||||||
self.str[valueOffset+1],
|
p.str[valueOffset+1],
|
||||||
})
|
}); err != nil {
|
||||||
if err != nil {
|
p.errors = append(p.errors, err)
|
||||||
self.errors = append(self.errors, err)
|
|
||||||
}
|
}
|
||||||
} else {
|
default:
|
||||||
// Should never, ever get here...
|
// Should never, ever get here...
|
||||||
self.error(-1, "re2: Illegal branch in scanEscape")
|
p.error(-1, "re2: Illegal branch in scanEscape")
|
||||||
goto skip
|
goto skip
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
skip:
|
skip:
|
||||||
_, err := self.goRegexp.WriteString(self.str[offset:self.chrOffset])
|
_, err := p.goRegexp.WriteString(p.str[offset:p.chrOffset])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
self.errors = append(self.errors, err)
|
p.errors = append(p.errors, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_RegExp_parser) pass() {
|
func (p *regExpParser) pass() {
|
||||||
if self.chr != -1 {
|
if p.chr != -1 {
|
||||||
_, err := self.goRegexp.WriteRune(self.chr)
|
_, err := p.goRegexp.WriteRune(p.chr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
self.errors = append(self.errors, err)
|
p.errors = append(p.errors, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.read()
|
p.read()
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Better error reporting, use the offset, etc.
|
// TODO Better error reporting, use the offset, etc.
|
||||||
func (self *_RegExp_parser) error(offset int, msg string, msgValues ...interface{}) error {
|
func (p *regExpParser) error(offset int, msg string, msgValues ...interface{}) { //nolint: unparam
|
||||||
err := fmt.Errorf(msg, msgValues...)
|
err := fmt.Errorf(msg, msgValues...)
|
||||||
self.errors = append(self.errors, err)
|
p.errors = append(p.errors, err)
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
26
v1/vendor/github.com/robertkrimen/otto/parser/scope.go
generated
vendored
|
@ -4,8 +4,8 @@ import (
|
||||||
"github.com/robertkrimen/otto/ast"
|
"github.com/robertkrimen/otto/ast"
|
||||||
)
|
)
|
||||||
|
|
||||||
type _scope struct {
|
type scope struct {
|
||||||
outer *_scope
|
outer *scope
|
||||||
allowIn bool
|
allowIn bool
|
||||||
inIteration bool
|
inIteration bool
|
||||||
inSwitch bool
|
inSwitch bool
|
||||||
|
@ -15,30 +15,30 @@ type _scope struct {
|
||||||
labels []string
|
labels []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_parser) openScope() {
|
func (p *parser) openScope() {
|
||||||
self.scope = &_scope{
|
p.scope = &scope{
|
||||||
outer: self.scope,
|
outer: p.scope,
|
||||||
allowIn: true,
|
allowIn: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_parser) closeScope() {
|
func (p *parser) closeScope() {
|
||||||
self.scope = self.scope.outer
|
p.scope = p.scope.outer
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_scope) declare(declaration ast.Declaration) {
|
func (p *scope) declare(declaration ast.Declaration) {
|
||||||
self.declarationList = append(self.declarationList, declaration)
|
p.declarationList = append(p.declarationList, declaration)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_scope) hasLabel(name string) bool {
|
func (p *scope) hasLabel(name string) bool {
|
||||||
for _, label := range self.labels {
|
for _, label := range p.labels {
|
||||||
if label == name {
|
if label == name {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if self.outer != nil && !self.inFunction {
|
if p.outer != nil && !p.inFunction {
|
||||||
// Crossing a function boundary to look for a label is verboten
|
// Crossing a function boundary to look for a label is verboten
|
||||||
return self.outer.hasLabel(name)
|
return p.outer.hasLabel(name)
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
850
v1/vendor/github.com/robertkrimen/otto/parser/statement.go
generated
vendored
157
v1/vendor/github.com/robertkrimen/otto/property.go
generated
vendored
|
@ -2,87 +2,87 @@ package otto
|
||||||
|
|
||||||
// property
|
// property
|
||||||
|
|
||||||
type _propertyMode int
|
type propertyMode int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
modeWriteMask _propertyMode = 0700
|
modeWriteMask propertyMode = 0o700
|
||||||
modeEnumerateMask = 0070
|
modeEnumerateMask propertyMode = 0o070
|
||||||
modeConfigureMask = 0007
|
modeConfigureMask propertyMode = 0o007
|
||||||
modeOnMask = 0111
|
modeOnMask propertyMode = 0o111
|
||||||
modeSetMask = 0222 // If value is 2, then mode is neither "On" nor "Off"
|
modeSetMask propertyMode = 0o222 // If value is 2, then mode is neither "On" nor "Off"
|
||||||
)
|
)
|
||||||
|
|
||||||
type _propertyGetSet [2]*_object
|
type propertyGetSet [2]*object
|
||||||
|
|
||||||
var _nilGetSetObject _object = _object{}
|
var nilGetSetObject = object{}
|
||||||
|
|
||||||
type _property struct {
|
type property struct {
|
||||||
value interface{}
|
value interface{}
|
||||||
mode _propertyMode
|
mode propertyMode
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self _property) writable() bool {
|
func (p property) writable() bool {
|
||||||
return self.mode&modeWriteMask == modeWriteMask&modeOnMask
|
return p.mode&modeWriteMask == modeWriteMask&modeOnMask
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_property) writeOn() {
|
func (p *property) writeOn() {
|
||||||
self.mode = (self.mode & ^modeWriteMask) | (modeWriteMask & modeOnMask)
|
p.mode = (p.mode & ^modeWriteMask) | (modeWriteMask & modeOnMask)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_property) writeOff() {
|
func (p *property) writeOff() {
|
||||||
self.mode &= ^modeWriteMask
|
p.mode &= ^modeWriteMask
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_property) writeClear() {
|
func (p *property) writeClear() {
|
||||||
self.mode = (self.mode & ^modeWriteMask) | (modeWriteMask & modeSetMask)
|
p.mode = (p.mode & ^modeWriteMask) | (modeWriteMask & modeSetMask)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self _property) writeSet() bool {
|
func (p property) writeSet() bool {
|
||||||
return 0 == self.mode&modeWriteMask&modeSetMask
|
return p.mode&modeWriteMask&modeSetMask == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self _property) enumerable() bool {
|
func (p property) enumerable() bool {
|
||||||
return self.mode&modeEnumerateMask == modeEnumerateMask&modeOnMask
|
return p.mode&modeEnumerateMask == modeEnumerateMask&modeOnMask
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_property) enumerateOn() {
|
func (p *property) enumerateOn() {
|
||||||
self.mode = (self.mode & ^modeEnumerateMask) | (modeEnumerateMask & modeOnMask)
|
p.mode = (p.mode & ^modeEnumerateMask) | (modeEnumerateMask & modeOnMask)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_property) enumerateOff() {
|
func (p *property) enumerateOff() {
|
||||||
self.mode &= ^modeEnumerateMask
|
p.mode &= ^modeEnumerateMask
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self _property) enumerateSet() bool {
|
func (p property) enumerateSet() bool {
|
||||||
return 0 == self.mode&modeEnumerateMask&modeSetMask
|
return p.mode&modeEnumerateMask&modeSetMask == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self _property) configurable() bool {
|
func (p property) configurable() bool {
|
||||||
return self.mode&modeConfigureMask == modeConfigureMask&modeOnMask
|
return p.mode&modeConfigureMask == modeConfigureMask&modeOnMask
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_property) configureOn() {
|
func (p *property) configureOn() {
|
||||||
self.mode = (self.mode & ^modeConfigureMask) | (modeConfigureMask & modeOnMask)
|
p.mode = (p.mode & ^modeConfigureMask) | (modeConfigureMask & modeOnMask)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_property) configureOff() {
|
func (p *property) configureOff() {
|
||||||
self.mode &= ^modeConfigureMask
|
p.mode &= ^modeConfigureMask
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self _property) configureSet() bool {
|
func (p property) configureSet() bool { //nolint: unused
|
||||||
return 0 == self.mode&modeConfigureMask&modeSetMask
|
return p.mode&modeConfigureMask&modeSetMask == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self _property) copy() *_property {
|
func (p property) copy() *property { //nolint: unused
|
||||||
property := self
|
cpy := p
|
||||||
return &property
|
return &cpy
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self _property) get(this *_object) Value {
|
func (p property) get(this *object) Value {
|
||||||
switch value := self.value.(type) {
|
switch value := p.value.(type) {
|
||||||
case Value:
|
case Value:
|
||||||
return value
|
return value
|
||||||
case _propertyGetSet:
|
case propertyGetSet:
|
||||||
if value[0] != nil {
|
if value[0] != nil {
|
||||||
return value[0].call(toValue(this), nil, false, nativeFrame)
|
return value[0].call(toValue(this), nil, false, nativeFrame)
|
||||||
}
|
}
|
||||||
|
@ -90,37 +90,37 @@ func (self _property) get(this *_object) Value {
|
||||||
return Value{}
|
return Value{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self _property) isAccessorDescriptor() bool {
|
func (p property) isAccessorDescriptor() bool {
|
||||||
setGet, test := self.value.(_propertyGetSet)
|
setGet, test := p.value.(propertyGetSet)
|
||||||
return test && (setGet[0] != nil || setGet[1] != nil)
|
return test && (setGet[0] != nil || setGet[1] != nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self _property) isDataDescriptor() bool {
|
func (p property) isDataDescriptor() bool {
|
||||||
if self.writeSet() { // Either "On" or "Off"
|
if p.writeSet() { // Either "On" or "Off"
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
value, valid := self.value.(Value)
|
value, valid := p.value.(Value)
|
||||||
return valid && !value.isEmpty()
|
return valid && !value.isEmpty()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self _property) isGenericDescriptor() bool {
|
func (p property) isGenericDescriptor() bool {
|
||||||
return !(self.isDataDescriptor() || self.isAccessorDescriptor())
|
return !(p.isDataDescriptor() || p.isAccessorDescriptor())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self _property) isEmpty() bool {
|
func (p property) isEmpty() bool {
|
||||||
return self.mode == 0222 && self.isGenericDescriptor()
|
return p.mode == 0o222 && p.isGenericDescriptor()
|
||||||
}
|
}
|
||||||
|
|
||||||
// _enumerableValue, _enumerableTrue, _enumerableFalse?
|
// _enumerableValue, _enumerableTrue, _enumerableFalse?
|
||||||
// .enumerableValue() .enumerableExists()
|
// .enumerableValue() .enumerableExists()
|
||||||
|
|
||||||
func toPropertyDescriptor(rt *_runtime, value Value) (descriptor _property) {
|
func toPropertyDescriptor(rt *runtime, value Value) property {
|
||||||
objectDescriptor := value._object()
|
objectDescriptor := value.object()
|
||||||
if objectDescriptor == nil {
|
if objectDescriptor == nil {
|
||||||
panic(rt.panicTypeError())
|
panic(rt.panicTypeError("toPropertyDescriptor on nil"))
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
var descriptor property
|
||||||
descriptor.mode = modeSetMask // Initially nothing is set
|
descriptor.mode = modeSetMask // Initially nothing is set
|
||||||
if objectDescriptor.hasProperty("enumerable") {
|
if objectDescriptor.hasProperty("enumerable") {
|
||||||
if objectDescriptor.get("enumerable").bool() {
|
if objectDescriptor.get("enumerable").bool() {
|
||||||
|
@ -145,21 +145,20 @@ func toPropertyDescriptor(rt *_runtime, value Value) (descriptor _property) {
|
||||||
descriptor.writeOff()
|
descriptor.writeOff()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
var getter, setter *_object
|
var getter, setter *object
|
||||||
getterSetter := false
|
getterSetter := false
|
||||||
|
|
||||||
if objectDescriptor.hasProperty("get") {
|
if objectDescriptor.hasProperty("get") {
|
||||||
value := objectDescriptor.get("get")
|
value := objectDescriptor.get("get")
|
||||||
if value.IsDefined() {
|
if value.IsDefined() {
|
||||||
if !value.isCallable() {
|
if !value.isCallable() {
|
||||||
panic(rt.panicTypeError())
|
panic(rt.panicTypeError("toPropertyDescriptor get not callable"))
|
||||||
}
|
}
|
||||||
getter = value._object()
|
getter = value.object()
|
||||||
getterSetter = true
|
getterSetter = true
|
||||||
} else {
|
} else {
|
||||||
getter = &_nilGetSetObject
|
getter = &nilGetSetObject
|
||||||
getterSetter = true
|
getterSetter = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -168,52 +167,52 @@ func toPropertyDescriptor(rt *_runtime, value Value) (descriptor _property) {
|
||||||
value := objectDescriptor.get("set")
|
value := objectDescriptor.get("set")
|
||||||
if value.IsDefined() {
|
if value.IsDefined() {
|
||||||
if !value.isCallable() {
|
if !value.isCallable() {
|
||||||
panic(rt.panicTypeError())
|
panic(rt.panicTypeError("toPropertyDescriptor set not callable"))
|
||||||
}
|
}
|
||||||
setter = value._object()
|
setter = value.object()
|
||||||
getterSetter = true
|
getterSetter = true
|
||||||
} else {
|
} else {
|
||||||
setter = &_nilGetSetObject
|
setter = &nilGetSetObject
|
||||||
getterSetter = true
|
getterSetter = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if getterSetter {
|
if getterSetter {
|
||||||
if descriptor.writeSet() {
|
if descriptor.writeSet() {
|
||||||
panic(rt.panicTypeError())
|
panic(rt.panicTypeError("toPropertyDescriptor descriptor writeSet"))
|
||||||
}
|
}
|
||||||
descriptor.value = _propertyGetSet{getter, setter}
|
descriptor.value = propertyGetSet{getter, setter}
|
||||||
}
|
}
|
||||||
|
|
||||||
if objectDescriptor.hasProperty("value") {
|
if objectDescriptor.hasProperty("value") {
|
||||||
if getterSetter {
|
if getterSetter {
|
||||||
panic(rt.panicTypeError())
|
panic(rt.panicTypeError("toPropertyDescriptor value getterSetter"))
|
||||||
}
|
}
|
||||||
descriptor.value = objectDescriptor.get("value")
|
descriptor.value = objectDescriptor.get("value")
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return descriptor
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_runtime) fromPropertyDescriptor(descriptor _property) *_object {
|
func (rt *runtime) fromPropertyDescriptor(descriptor property) *object {
|
||||||
object := self.newObject()
|
obj := rt.newObject()
|
||||||
if descriptor.isDataDescriptor() {
|
if descriptor.isDataDescriptor() {
|
||||||
object.defineProperty("value", descriptor.value.(Value), 0111, false)
|
obj.defineProperty("value", descriptor.value.(Value), 0o111, false)
|
||||||
object.defineProperty("writable", toValue_bool(descriptor.writable()), 0111, false)
|
obj.defineProperty("writable", boolValue(descriptor.writable()), 0o111, false)
|
||||||
} else if descriptor.isAccessorDescriptor() {
|
} else if descriptor.isAccessorDescriptor() {
|
||||||
getSet := descriptor.value.(_propertyGetSet)
|
getSet := descriptor.value.(propertyGetSet)
|
||||||
get := Value{}
|
get := Value{}
|
||||||
if getSet[0] != nil {
|
if getSet[0] != nil {
|
||||||
get = toValue_object(getSet[0])
|
get = objectValue(getSet[0])
|
||||||
}
|
}
|
||||||
set := Value{}
|
set := Value{}
|
||||||
if getSet[1] != nil {
|
if getSet[1] != nil {
|
||||||
set = toValue_object(getSet[1])
|
set = objectValue(getSet[1])
|
||||||
}
|
}
|
||||||
object.defineProperty("get", get, 0111, false)
|
obj.defineProperty("get", get, 0o111, false)
|
||||||
object.defineProperty("set", set, 0111, false)
|
obj.defineProperty("set", set, 0o111, false)
|
||||||
}
|
}
|
||||||
object.defineProperty("enumerable", toValue_bool(descriptor.enumerable()), 0111, false)
|
obj.defineProperty("enumerable", boolValue(descriptor.enumerable()), 0o111, false)
|
||||||
object.defineProperty("configurable", toValue_bool(descriptor.configurable()), 0111, false)
|
obj.defineProperty("configurable", boolValue(descriptor.configurable()), 0o111, false)
|
||||||
return object
|
return obj
|
||||||
}
|
}
|
||||||
|
|
51
v1/vendor/github.com/robertkrimen/otto/registry/README.markdown
generated
vendored
|
@ -1,51 +0,0 @@
|
||||||
# registry
|
|
||||||
--
|
|
||||||
import "github.com/robertkrimen/otto/registry"
|
|
||||||
|
|
||||||
Package registry is an expirmental package to facillitate altering the otto
|
|
||||||
runtime via import.
|
|
||||||
|
|
||||||
This interface can change at any time.
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
#### func Apply
|
|
||||||
|
|
||||||
```go
|
|
||||||
func Apply(callback func(Entry))
|
|
||||||
```
|
|
||||||
|
|
||||||
#### type Entry
|
|
||||||
|
|
||||||
```go
|
|
||||||
type Entry struct {
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
#### func Register
|
|
||||||
|
|
||||||
```go
|
|
||||||
func Register(source func() string) *Entry
|
|
||||||
```
|
|
||||||
|
|
||||||
#### func (*Entry) Disable
|
|
||||||
|
|
||||||
```go
|
|
||||||
func (self *Entry) Disable()
|
|
||||||
```
|
|
||||||
|
|
||||||
#### func (*Entry) Enable
|
|
||||||
|
|
||||||
```go
|
|
||||||
func (self *Entry) Enable()
|
|
||||||
```
|
|
||||||
|
|
||||||
#### func (Entry) Source
|
|
||||||
|
|
||||||
```go
|
|
||||||
func (self Entry) Source() string
|
|
||||||
```
|
|
||||||
|
|
||||||
--
|
|
||||||
**godocdown** http://github.com/robertkrimen/godocdown
|
|
27
v1/vendor/github.com/robertkrimen/otto/registry/registry.go
generated
vendored
|
@ -1,17 +1,17 @@
|
||||||
/*
|
// Package registry is an experimental package to facilitate altering the otto runtime via import.
|
||||||
Package registry is an expirmental package to facillitate altering the otto runtime via import.
|
//
|
||||||
|
// This interface can change at any time.
|
||||||
This interface can change at any time.
|
|
||||||
*/
|
|
||||||
package registry
|
package registry
|
||||||
|
|
||||||
var registry []*Entry = make([]*Entry, 0)
|
var registry []*Entry = make([]*Entry, 0)
|
||||||
|
|
||||||
|
// Entry represents a registry entry.
|
||||||
type Entry struct {
|
type Entry struct {
|
||||||
active bool
|
active bool
|
||||||
source func() string
|
source func() string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// newEntry returns a new Entry for source.
|
||||||
func newEntry(source func() string) *Entry {
|
func newEntry(source func() string) *Entry {
|
||||||
return &Entry{
|
return &Entry{
|
||||||
active: true,
|
active: true,
|
||||||
|
@ -19,18 +19,22 @@ func newEntry(source func() string) *Entry {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *Entry) Enable() {
|
// Enable enables the entry.
|
||||||
self.active = true
|
func (e *Entry) Enable() {
|
||||||
|
e.active = true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *Entry) Disable() {
|
// Disable disables the entry.
|
||||||
self.active = false
|
func (e *Entry) Disable() {
|
||||||
|
e.active = false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self Entry) Source() string {
|
// Source returns the source of the entry.
|
||||||
return self.source()
|
func (e Entry) Source() string {
|
||||||
|
return e.source()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Apply applies callback to all registry entries.
|
||||||
func Apply(callback func(Entry)) {
|
func Apply(callback func(Entry)) {
|
||||||
for _, entry := range registry {
|
for _, entry := range registry {
|
||||||
if !entry.active {
|
if !entry.active {
|
||||||
|
@ -40,6 +44,7 @@ func Apply(callback func(Entry)) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Register registers a new Entry for source.
|
||||||
func Register(source func() string) *Entry {
|
func Register(source func() string) *Entry {
|
||||||
entry := newEntry(source)
|
entry := newEntry(source)
|
||||||
registry = append(registry, entry)
|
registry = append(registry, entry)
|
||||||
|
|
20
v1/vendor/github.com/robertkrimen/otto/result.go
generated
vendored
|
@ -1,28 +1,28 @@
|
||||||
package otto
|
package otto
|
||||||
|
|
||||||
type _resultKind int
|
type resultKind int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
_ _resultKind = iota
|
_ resultKind = iota
|
||||||
resultReturn
|
resultReturn
|
||||||
resultBreak
|
resultBreak
|
||||||
resultContinue
|
resultContinue
|
||||||
)
|
)
|
||||||
|
|
||||||
type _result struct {
|
type result struct {
|
||||||
kind _resultKind
|
kind resultKind
|
||||||
value Value
|
value Value
|
||||||
target string
|
target string
|
||||||
}
|
}
|
||||||
|
|
||||||
func newReturnResult(value Value) _result {
|
func newReturnResult(value Value) result {
|
||||||
return _result{resultReturn, value, ""}
|
return result{resultReturn, value, ""}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newContinueResult(target string) _result {
|
func newContinueResult(target string) result {
|
||||||
return _result{resultContinue, emptyValue, target}
|
return result{resultContinue, emptyValue, target}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newBreakResult(target string) _result {
|
func newBreakResult(target string) result {
|
||||||
return _result{resultBreak, emptyValue, target}
|
return result{resultBreak, emptyValue, target}
|
||||||
}
|
}
|
||||||
|
|
413
v1/vendor/github.com/robertkrimen/otto/runtime.go
generated
vendored
|
@ -8,7 +8,7 @@ import (
|
||||||
"math"
|
"math"
|
||||||
"path"
|
"path"
|
||||||
"reflect"
|
"reflect"
|
||||||
"runtime"
|
goruntime "runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
@ -17,49 +17,49 @@ import (
|
||||||
"github.com/robertkrimen/otto/parser"
|
"github.com/robertkrimen/otto/parser"
|
||||||
)
|
)
|
||||||
|
|
||||||
type _global struct {
|
type global struct {
|
||||||
Object *_object // Object( ... ), new Object( ... ) - 1 (length)
|
Object *object // Object( ... ), new Object( ... ) - 1 (length)
|
||||||
Function *_object // Function( ... ), new Function( ... ) - 1
|
Function *object // Function( ... ), new Function( ... ) - 1
|
||||||
Array *_object // Array( ... ), new Array( ... ) - 1
|
Array *object // Array( ... ), new Array( ... ) - 1
|
||||||
String *_object // String( ... ), new String( ... ) - 1
|
String *object // String( ... ), new String( ... ) - 1
|
||||||
Boolean *_object // Boolean( ... ), new Boolean( ... ) - 1
|
Boolean *object // Boolean( ... ), new Boolean( ... ) - 1
|
||||||
Number *_object // Number( ... ), new Number( ... ) - 1
|
Number *object // Number( ... ), new Number( ... ) - 1
|
||||||
Math *_object
|
Math *object
|
||||||
Date *_object // Date( ... ), new Date( ... ) - 7
|
Date *object // Date( ... ), new Date( ... ) - 7
|
||||||
RegExp *_object // RegExp( ... ), new RegExp( ... ) - 2
|
RegExp *object // RegExp( ... ), new RegExp( ... ) - 2
|
||||||
Error *_object // Error( ... ), new Error( ... ) - 1
|
Error *object // Error( ... ), new Error( ... ) - 1
|
||||||
EvalError *_object
|
EvalError *object
|
||||||
TypeError *_object
|
TypeError *object
|
||||||
RangeError *_object
|
RangeError *object
|
||||||
ReferenceError *_object
|
ReferenceError *object
|
||||||
SyntaxError *_object
|
SyntaxError *object
|
||||||
URIError *_object
|
URIError *object
|
||||||
JSON *_object
|
JSON *object
|
||||||
|
|
||||||
ObjectPrototype *_object // Object.prototype
|
ObjectPrototype *object // Object.prototype
|
||||||
FunctionPrototype *_object // Function.prototype
|
FunctionPrototype *object // Function.prototype
|
||||||
ArrayPrototype *_object // Array.prototype
|
ArrayPrototype *object // Array.prototype
|
||||||
StringPrototype *_object // String.prototype
|
StringPrototype *object // String.prototype
|
||||||
BooleanPrototype *_object // Boolean.prototype
|
BooleanPrototype *object // Boolean.prototype
|
||||||
NumberPrototype *_object // Number.prototype
|
NumberPrototype *object // Number.prototype
|
||||||
DatePrototype *_object // Date.prototype
|
DatePrototype *object // Date.prototype
|
||||||
RegExpPrototype *_object // RegExp.prototype
|
RegExpPrototype *object // RegExp.prototype
|
||||||
ErrorPrototype *_object // Error.prototype
|
ErrorPrototype *object // Error.prototype
|
||||||
EvalErrorPrototype *_object
|
EvalErrorPrototype *object
|
||||||
TypeErrorPrototype *_object
|
TypeErrorPrototype *object
|
||||||
RangeErrorPrototype *_object
|
RangeErrorPrototype *object
|
||||||
ReferenceErrorPrototype *_object
|
ReferenceErrorPrototype *object
|
||||||
SyntaxErrorPrototype *_object
|
SyntaxErrorPrototype *object
|
||||||
URIErrorPrototype *_object
|
URIErrorPrototype *object
|
||||||
}
|
}
|
||||||
|
|
||||||
type _runtime struct {
|
type runtime struct {
|
||||||
global _global
|
global global
|
||||||
globalObject *_object
|
globalObject *object
|
||||||
globalStash *_objectStash
|
globalStash *objectStash
|
||||||
scope *_scope
|
scope *scope
|
||||||
otto *Otto
|
otto *Otto
|
||||||
eval *_object // The builtin eval, for determine indirect versus direct invocation
|
eval *object // The builtin eval, for determine indirect versus direct invocation
|
||||||
debugger func(*Otto)
|
debugger func(*Otto)
|
||||||
random func() float64
|
random func() float64
|
||||||
stackLimit int
|
stackLimit int
|
||||||
|
@ -69,54 +69,54 @@ type _runtime struct {
|
||||||
lck sync.Mutex
|
lck sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_runtime) enterScope(scope *_scope) {
|
func (rt *runtime) enterScope(scop *scope) {
|
||||||
scope.outer = self.scope
|
scop.outer = rt.scope
|
||||||
if self.scope != nil {
|
if rt.scope != nil {
|
||||||
if self.stackLimit != 0 && self.scope.depth+1 >= self.stackLimit {
|
if rt.stackLimit != 0 && rt.scope.depth+1 >= rt.stackLimit {
|
||||||
panic(self.panicRangeError("Maximum call stack size exceeded"))
|
panic(rt.panicRangeError("Maximum call stack size exceeded"))
|
||||||
}
|
}
|
||||||
|
|
||||||
scope.depth = self.scope.depth + 1
|
scop.depth = rt.scope.depth + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
self.scope = scope
|
rt.scope = scop
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_runtime) leaveScope() {
|
func (rt *runtime) leaveScope() {
|
||||||
self.scope = self.scope.outer
|
rt.scope = rt.scope.outer
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME This is used in two places (cloning)
|
// FIXME This is used in two places (cloning).
|
||||||
func (self *_runtime) enterGlobalScope() {
|
func (rt *runtime) enterGlobalScope() {
|
||||||
self.enterScope(newScope(self.globalStash, self.globalStash, self.globalObject))
|
rt.enterScope(newScope(rt.globalStash, rt.globalStash, rt.globalObject))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_runtime) enterFunctionScope(outer _stash, this Value) *_fnStash {
|
func (rt *runtime) enterFunctionScope(outer stasher, this Value) *fnStash {
|
||||||
if outer == nil {
|
if outer == nil {
|
||||||
outer = self.globalStash
|
outer = rt.globalStash
|
||||||
}
|
}
|
||||||
stash := self.newFunctionStash(outer)
|
stash := rt.newFunctionStash(outer)
|
||||||
var thisObject *_object
|
var thisObject *object
|
||||||
switch this.kind {
|
switch this.kind {
|
||||||
case valueUndefined, valueNull:
|
case valueUndefined, valueNull:
|
||||||
thisObject = self.globalObject
|
thisObject = rt.globalObject
|
||||||
default:
|
default:
|
||||||
thisObject = self.toObject(this)
|
thisObject = rt.toObject(this)
|
||||||
}
|
}
|
||||||
self.enterScope(newScope(stash, stash, thisObject))
|
rt.enterScope(newScope(stash, stash, thisObject))
|
||||||
return stash
|
return stash
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_runtime) putValue(reference _reference, value Value) {
|
func (rt *runtime) putValue(reference referencer, value Value) {
|
||||||
name := reference.putValue(value)
|
name := reference.putValue(value)
|
||||||
if name != "" {
|
if name != "" {
|
||||||
// Why? -- If reference.base == nil
|
// Why? -- If reference.base == nil
|
||||||
// strict = false
|
// strict = false
|
||||||
self.globalObject.defineProperty(name, value, 0111, false)
|
rt.globalObject.defineProperty(name, value, 0o111, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_runtime) tryCatchEvaluate(inner func() Value) (tryValue Value, exception bool) {
|
func (rt *runtime) tryCatchEvaluate(inner func() Value) (tryValue Value, isException bool) { //nolint: nonamedreturns
|
||||||
// resultValue = The value of the block (e.g. the last statement)
|
// resultValue = The value of the block (e.g. the last statement)
|
||||||
// throw = Something was thrown
|
// throw = Something was thrown
|
||||||
// throwValue = The value of what was thrown
|
// throwValue = The value of what was thrown
|
||||||
|
@ -124,18 +124,18 @@ func (self *_runtime) tryCatchEvaluate(inner func() Value) (tryValue Value, exce
|
||||||
// Otherwise, some sort of unknown panic happened, we'll just propagate it.
|
// Otherwise, some sort of unknown panic happened, we'll just propagate it.
|
||||||
defer func() {
|
defer func() {
|
||||||
if caught := recover(); caught != nil {
|
if caught := recover(); caught != nil {
|
||||||
if exception, ok := caught.(*_exception); ok {
|
if excep, ok := caught.(*exception); ok {
|
||||||
caught = exception.eject()
|
caught = excep.eject()
|
||||||
}
|
}
|
||||||
switch caught := caught.(type) {
|
switch caught := caught.(type) {
|
||||||
case _error:
|
case ottoError:
|
||||||
exception = true
|
isException = true
|
||||||
tryValue = toValue_object(self.newErrorObjectError(caught))
|
tryValue = objectValue(rt.newErrorObjectError(caught))
|
||||||
case Value:
|
case Value:
|
||||||
exception = true
|
isException = true
|
||||||
tryValue = caught
|
tryValue = caught
|
||||||
default:
|
default:
|
||||||
exception = true
|
isException = true
|
||||||
tryValue = toValue(caught)
|
tryValue = toValue(caught)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -144,52 +144,51 @@ func (self *_runtime) tryCatchEvaluate(inner func() Value) (tryValue Value, exce
|
||||||
return inner(), false
|
return inner(), false
|
||||||
}
|
}
|
||||||
|
|
||||||
// toObject
|
func (rt *runtime) toObject(value Value) *object {
|
||||||
|
|
||||||
func (self *_runtime) toObject(value Value) *_object {
|
|
||||||
switch value.kind {
|
switch value.kind {
|
||||||
case valueEmpty, valueUndefined, valueNull:
|
case valueEmpty, valueUndefined, valueNull:
|
||||||
panic(self.panicTypeError())
|
panic(rt.panicTypeError("toObject unsupported kind %s", value.kind))
|
||||||
case valueBoolean:
|
case valueBoolean:
|
||||||
return self.newBoolean(value)
|
return rt.newBoolean(value)
|
||||||
case valueString:
|
case valueString:
|
||||||
return self.newString(value)
|
return rt.newString(value)
|
||||||
case valueNumber:
|
case valueNumber:
|
||||||
return self.newNumber(value)
|
return rt.newNumber(value)
|
||||||
case valueObject:
|
case valueObject:
|
||||||
return value._object()
|
return value.object()
|
||||||
|
default:
|
||||||
|
panic(rt.panicTypeError("toObject unknown kind %s", value.kind))
|
||||||
}
|
}
|
||||||
panic(self.panicTypeError())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_runtime) objectCoerce(value Value) (*_object, error) {
|
func (rt *runtime) objectCoerce(value Value) (*object, error) {
|
||||||
switch value.kind {
|
switch value.kind {
|
||||||
case valueUndefined:
|
case valueUndefined:
|
||||||
return nil, errors.New("undefined")
|
return nil, errors.New("undefined")
|
||||||
case valueNull:
|
case valueNull:
|
||||||
return nil, errors.New("null")
|
return nil, errors.New("null")
|
||||||
case valueBoolean:
|
case valueBoolean:
|
||||||
return self.newBoolean(value), nil
|
return rt.newBoolean(value), nil
|
||||||
case valueString:
|
case valueString:
|
||||||
return self.newString(value), nil
|
return rt.newString(value), nil
|
||||||
case valueNumber:
|
case valueNumber:
|
||||||
return self.newNumber(value), nil
|
return rt.newNumber(value), nil
|
||||||
case valueObject:
|
case valueObject:
|
||||||
return value._object(), nil
|
return value.object(), nil
|
||||||
|
default:
|
||||||
|
panic(rt.panicTypeError("objectCoerce unknown kind %s", value.kind))
|
||||||
}
|
}
|
||||||
panic(self.panicTypeError())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkObjectCoercible(rt *_runtime, value Value) {
|
func checkObjectCoercible(rt *runtime, value Value) {
|
||||||
isObject, mustCoerce := testObjectCoercible(value)
|
isObject, mustCoerce := testObjectCoercible(value)
|
||||||
if !isObject && !mustCoerce {
|
if !isObject && !mustCoerce {
|
||||||
panic(rt.panicTypeError())
|
panic(rt.panicTypeError("checkObjectCoercible not object or mustCoerce"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// testObjectCoercible
|
// testObjectCoercible.
|
||||||
|
func testObjectCoercible(value Value) (isObject, mustCoerce bool) { //nolint: nonamedreturns
|
||||||
func testObjectCoercible(value Value) (isObject bool, mustCoerce bool) {
|
|
||||||
switch value.kind {
|
switch value.kind {
|
||||||
case valueReference, valueEmpty, valueNull, valueUndefined:
|
case valueReference, valueEmpty, valueNull, valueUndefined:
|
||||||
return false, false
|
return false, false
|
||||||
|
@ -198,21 +197,21 @@ func testObjectCoercible(value Value) (isObject bool, mustCoerce bool) {
|
||||||
case valueObject:
|
case valueObject:
|
||||||
return true, false
|
return true, false
|
||||||
default:
|
default:
|
||||||
panic("this should never happen")
|
panic(fmt.Sprintf("testObjectCoercible unknown kind %s", value.kind))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_runtime) safeToValue(value interface{}) (Value, error) {
|
func (rt *runtime) safeToValue(value interface{}) (Value, error) {
|
||||||
result := Value{}
|
result := Value{}
|
||||||
err := catchPanic(func() {
|
err := catchPanic(func() {
|
||||||
result = self.toValue(value)
|
result = rt.toValue(value)
|
||||||
})
|
})
|
||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// convertNumeric converts numeric parameter val from js to that of type t if it is safe to do so, otherwise it panics.
|
// convertNumeric converts numeric parameter val from js to that of type t if it is safe to do so, otherwise it panics.
|
||||||
// This allows literals (int64), bitwise values (int32) and the general form (float64) of javascript numerics to be passed as parameters to go functions easily.
|
// This allows literals (int64), bitwise values (int32) and the general form (float64) of javascript numerics to be passed as parameters to go functions easily.
|
||||||
func (self *_runtime) convertNumeric(v Value, t reflect.Type) reflect.Value {
|
func (rt *runtime) convertNumeric(v Value, t reflect.Type) reflect.Value {
|
||||||
val := reflect.ValueOf(v.export())
|
val := reflect.ValueOf(v.export())
|
||||||
|
|
||||||
if val.Kind() == t.Kind() {
|
if val.Kind() == t.Kind() {
|
||||||
|
@ -231,20 +230,20 @@ func (self *_runtime) convertNumeric(v Value, t reflect.Type) reflect.Value {
|
||||||
return reflect.ValueOf(f64)
|
return reflect.ValueOf(f64)
|
||||||
case reflect.Float32:
|
case reflect.Float32:
|
||||||
if reflect.Zero(t).OverflowFloat(f64) {
|
if reflect.Zero(t).OverflowFloat(f64) {
|
||||||
panic(self.panicRangeError("converting float64 to float32 would overflow"))
|
panic(rt.panicRangeError("converting float64 to float32 would overflow"))
|
||||||
}
|
}
|
||||||
|
|
||||||
return val.Convert(t)
|
return val.Convert(t)
|
||||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||||
i64 := int64(f64)
|
i64 := int64(f64)
|
||||||
if float64(i64) != f64 {
|
if float64(i64) != f64 {
|
||||||
panic(self.panicRangeError(fmt.Sprintf("converting %v to %v would cause loss of precision", val.Type(), t)))
|
panic(rt.panicRangeError(fmt.Sprintf("converting %v to %v would cause loss of precision", val.Type(), t)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// The float represents an integer
|
// The float represents an integer
|
||||||
val = reflect.ValueOf(i64)
|
val = reflect.ValueOf(i64)
|
||||||
default:
|
default:
|
||||||
panic(self.panicTypeError(fmt.Sprintf("cannot convert %v to %v", val.Type(), t)))
|
panic(rt.panicTypeError(fmt.Sprintf("cannot convert %v to %v", val.Type(), t)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -254,15 +253,15 @@ func (self *_runtime) convertNumeric(v Value, t reflect.Type) reflect.Value {
|
||||||
switch t.Kind() {
|
switch t.Kind() {
|
||||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
if reflect.Zero(t).OverflowInt(i64) {
|
if reflect.Zero(t).OverflowInt(i64) {
|
||||||
panic(self.panicRangeError(fmt.Sprintf("converting %v to %v would overflow", val.Type(), t)))
|
panic(rt.panicRangeError(fmt.Sprintf("converting %v to %v would overflow", val.Type(), t)))
|
||||||
}
|
}
|
||||||
return val.Convert(t)
|
return val.Convert(t)
|
||||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||||
if i64 < 0 {
|
if i64 < 0 {
|
||||||
panic(self.panicRangeError(fmt.Sprintf("converting %v to %v would underflow", val.Type(), t)))
|
panic(rt.panicRangeError(fmt.Sprintf("converting %v to %v would underflow", val.Type(), t)))
|
||||||
}
|
}
|
||||||
if reflect.Zero(t).OverflowUint(uint64(i64)) {
|
if reflect.Zero(t).OverflowUint(uint64(i64)) {
|
||||||
panic(self.panicRangeError(fmt.Sprintf("converting %v to %v would overflow", val.Type(), t)))
|
panic(rt.panicRangeError(fmt.Sprintf("converting %v to %v would overflow", val.Type(), t)))
|
||||||
}
|
}
|
||||||
return val.Convert(t)
|
return val.Convert(t)
|
||||||
case reflect.Float32, reflect.Float64:
|
case reflect.Float32, reflect.Float64:
|
||||||
|
@ -274,12 +273,12 @@ func (self *_runtime) convertNumeric(v Value, t reflect.Type) reflect.Value {
|
||||||
switch t.Kind() {
|
switch t.Kind() {
|
||||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
if u64 > math.MaxInt64 || reflect.Zero(t).OverflowInt(int64(u64)) {
|
if u64 > math.MaxInt64 || reflect.Zero(t).OverflowInt(int64(u64)) {
|
||||||
panic(self.panicRangeError(fmt.Sprintf("converting %v to %v would overflow", val.Type(), t)))
|
panic(rt.panicRangeError(fmt.Sprintf("converting %v to %v would overflow", val.Type(), t)))
|
||||||
}
|
}
|
||||||
return val.Convert(t)
|
return val.Convert(t)
|
||||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||||
if reflect.Zero(t).OverflowUint(u64) {
|
if reflect.Zero(t).OverflowUint(u64) {
|
||||||
panic(self.panicRangeError(fmt.Sprintf("converting %v to %v would overflow", val.Type(), t)))
|
panic(rt.panicRangeError(fmt.Sprintf("converting %v to %v would overflow", val.Type(), t)))
|
||||||
}
|
}
|
||||||
return val.Convert(t)
|
return val.Convert(t)
|
||||||
case reflect.Float32, reflect.Float64:
|
case reflect.Float32, reflect.Float64:
|
||||||
|
@ -287,7 +286,7 @@ func (self *_runtime) convertNumeric(v Value, t reflect.Type) reflect.Value {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
panic(self.panicTypeError(fmt.Sprintf("unsupported type %v -> %v for numeric conversion", val.Type(), t)))
|
panic(rt.panicTypeError(fmt.Sprintf("unsupported type %v -> %v for numeric conversion", val.Type(), t)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func fieldIndexByName(t reflect.Type, name string) []int {
|
func fieldIndexByName(t reflect.Type, name string) []int {
|
||||||
|
@ -332,13 +331,15 @@ func fieldIndexByName(t reflect.Type, name string) []int {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var typeOfValue = reflect.TypeOf(Value{})
|
var (
|
||||||
var typeOfJSONRawMessage = reflect.TypeOf(json.RawMessage{})
|
typeOfValue = reflect.TypeOf(Value{})
|
||||||
|
typeOfJSONRawMessage = reflect.TypeOf(json.RawMessage{})
|
||||||
|
)
|
||||||
|
|
||||||
// convertCallParameter converts request val to type t if possible.
|
// convertCallParameter converts request val to type t if possible.
|
||||||
// If the conversion fails due to overflow or type miss-match then it panics.
|
// If the conversion fails due to overflow or type miss-match then it panics.
|
||||||
// If no conversion is known then the original value is returned.
|
// If no conversion is known then the original value is returned.
|
||||||
func (self *_runtime) convertCallParameter(v Value, t reflect.Type) (reflect.Value, error) {
|
func (rt *runtime) convertCallParameter(v Value, t reflect.Type) (reflect.Value, error) {
|
||||||
if t == typeOfValue {
|
if t == typeOfValue {
|
||||||
return reflect.ValueOf(v), nil
|
return reflect.ValueOf(v), nil
|
||||||
}
|
}
|
||||||
|
@ -350,25 +351,23 @@ func (self *_runtime) convertCallParameter(v Value, t reflect.Type) (reflect.Val
|
||||||
}
|
}
|
||||||
|
|
||||||
if v.kind == valueObject {
|
if v.kind == valueObject {
|
||||||
if gso, ok := v._object().value.(*_goStructObject); ok {
|
if gso, ok := v.object().value.(*goStructObject); ok {
|
||||||
if gso.value.Type().AssignableTo(t) {
|
if gso.value.Type().AssignableTo(t) {
|
||||||
// please see TestDynamicFunctionReturningInterface for why this exists
|
// please see TestDynamicFunctionReturningInterface for why this exists
|
||||||
if t.Kind() == reflect.Interface && gso.value.Type().ConvertibleTo(t) {
|
if t.Kind() == reflect.Interface && gso.value.Type().ConvertibleTo(t) {
|
||||||
return gso.value.Convert(t), nil
|
return gso.value.Convert(t), nil
|
||||||
} else {
|
}
|
||||||
return gso.value, nil
|
return gso.value, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if gao, ok := v._object().value.(*_goArrayObject); ok {
|
if gao, ok := v.object().value.(*goArrayObject); ok {
|
||||||
if gao.value.Type().AssignableTo(t) {
|
if gao.value.Type().AssignableTo(t) {
|
||||||
// please see TestDynamicFunctionReturningInterface for why this exists
|
// please see TestDynamicFunctionReturningInterface for why this exists
|
||||||
if t.Kind() == reflect.Interface && gao.value.Type().ConvertibleTo(t) {
|
if t.Kind() == reflect.Interface && gao.value.Type().ConvertibleTo(t) {
|
||||||
return gao.value.Convert(t), nil
|
return gao.value.Convert(t), nil
|
||||||
} else {
|
|
||||||
return gao.value, nil
|
|
||||||
}
|
}
|
||||||
|
return gao.value, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -392,9 +391,9 @@ func (self *_runtime) convertCallParameter(v Value, t reflect.Type) (reflect.Val
|
||||||
return reflect.Zero(t), nil
|
return reflect.Zero(t), nil
|
||||||
default:
|
default:
|
||||||
var vv reflect.Value
|
var vv reflect.Value
|
||||||
vv, err := self.convertCallParameter(v, t.Elem())
|
vv, err := rt.convertCallParameter(v, t.Elem())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reflect.Zero(t), fmt.Errorf("can't convert to %s: %s", t, err.Error())
|
return reflect.Zero(t), fmt.Errorf("can't convert to %s: %w", t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if vv.CanAddr() {
|
if vv.CanAddr() {
|
||||||
|
@ -418,12 +417,11 @@ func (self *_runtime) convertCallParameter(v Value, t reflect.Type) (reflect.Val
|
||||||
return reflect.ValueOf(fmt.Sprintf("%v", v.value)), nil
|
return reflect.ValueOf(fmt.Sprintf("%v", v.value)), nil
|
||||||
}
|
}
|
||||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64:
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64:
|
||||||
switch v.kind {
|
if v.kind == valueNumber {
|
||||||
case valueNumber:
|
return rt.convertNumeric(v, t), nil
|
||||||
return self.convertNumeric(v, t), nil
|
|
||||||
}
|
}
|
||||||
case reflect.Slice:
|
case reflect.Slice:
|
||||||
if o := v._object(); o != nil {
|
if o := v.object(); o != nil {
|
||||||
if lv := o.get(propertyLength); lv.IsNumber() {
|
if lv := o.get(propertyLength); lv.IsNumber() {
|
||||||
l := lv.number().int64
|
l := lv.number().int64
|
||||||
|
|
||||||
|
@ -432,7 +430,7 @@ func (self *_runtime) convertCallParameter(v Value, t reflect.Type) (reflect.Val
|
||||||
tt := t.Elem()
|
tt := t.Elem()
|
||||||
|
|
||||||
switch o.class {
|
switch o.class {
|
||||||
case classArray:
|
case classArrayName:
|
||||||
for i := int64(0); i < l; i++ {
|
for i := int64(0); i < l; i++ {
|
||||||
p, ok := o.property[strconv.FormatInt(i, 10)]
|
p, ok := o.property[strconv.FormatInt(i, 10)]
|
||||||
if !ok {
|
if !ok {
|
||||||
|
@ -444,24 +442,24 @@ func (self *_runtime) convertCallParameter(v Value, t reflect.Type) (reflect.Val
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
ev, err := self.convertCallParameter(e, tt)
|
ev, err := rt.convertCallParameter(e, tt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reflect.Zero(t), fmt.Errorf("couldn't convert element %d of %s: %s", i, t, err.Error())
|
return reflect.Zero(t), fmt.Errorf("couldn't convert element %d of %s: %w", i, t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
s.Index(int(i)).Set(ev)
|
s.Index(int(i)).Set(ev)
|
||||||
}
|
}
|
||||||
case classGoArray, classGoSlice:
|
case classGoArrayName, classGoSliceName:
|
||||||
var gslice bool
|
var gslice bool
|
||||||
switch o.value.(type) {
|
switch o.value.(type) {
|
||||||
case *_goSliceObject:
|
case *goSliceObject:
|
||||||
gslice = true
|
gslice = true
|
||||||
case *_goArrayObject:
|
case *goArrayObject:
|
||||||
gslice = false
|
gslice = false
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := int64(0); i < l; i++ {
|
for i := int64(0); i < l; i++ {
|
||||||
var p *_property
|
var p *property
|
||||||
if gslice {
|
if gslice {
|
||||||
p = goSliceGetOwnProperty(o, strconv.FormatInt(i, 10))
|
p = goSliceGetOwnProperty(o, strconv.FormatInt(i, 10))
|
||||||
} else {
|
} else {
|
||||||
|
@ -476,9 +474,9 @@ func (self *_runtime) convertCallParameter(v Value, t reflect.Type) (reflect.Val
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
ev, err := self.convertCallParameter(e, tt)
|
ev, err := rt.convertCallParameter(e, tt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reflect.Zero(t), fmt.Errorf("couldn't convert element %d of %s: %s", i, t, err.Error())
|
return reflect.Zero(t), fmt.Errorf("couldn't convert element %d of %s: %w", i, t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
s.Index(int(i)).Set(ev)
|
s.Index(int(i)).Set(ev)
|
||||||
|
@ -489,15 +487,15 @@ func (self *_runtime) convertCallParameter(v Value, t reflect.Type) (reflect.Val
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case reflect.Map:
|
case reflect.Map:
|
||||||
if o := v._object(); o != nil && t.Key().Kind() == reflect.String {
|
if o := v.object(); o != nil && t.Key().Kind() == reflect.String {
|
||||||
m := reflect.MakeMap(t)
|
m := reflect.MakeMap(t)
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
o.enumerate(false, func(k string) bool {
|
o.enumerate(false, func(k string) bool {
|
||||||
v, verr := self.convertCallParameter(o.get(k), t.Elem())
|
v, verr := rt.convertCallParameter(o.get(k), t.Elem())
|
||||||
if verr != nil {
|
if verr != nil {
|
||||||
err = fmt.Errorf("couldn't convert property %q of %s: %s", k, t, verr.Error())
|
err = fmt.Errorf("couldn't convert property %q of %s: %w", k, t, verr)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
m.SetMapIndex(reflect.ValueOf(k), v)
|
m.SetMapIndex(reflect.ValueOf(k), v)
|
||||||
|
@ -515,7 +513,7 @@ func (self *_runtime) convertCallParameter(v Value, t reflect.Type) (reflect.Val
|
||||||
return reflect.Zero(t), fmt.Errorf("converting JavaScript values to Go functions with more than one return value is currently not supported")
|
return reflect.Zero(t), fmt.Errorf("converting JavaScript values to Go functions with more than one return value is currently not supported")
|
||||||
}
|
}
|
||||||
|
|
||||||
if o := v._object(); o != nil && o.class == classFunction {
|
if o := v.object(); o != nil && o.class == classFunctionName {
|
||||||
return reflect.MakeFunc(t, func(args []reflect.Value) []reflect.Value {
|
return reflect.MakeFunc(t, func(args []reflect.Value) []reflect.Value {
|
||||||
l := make([]interface{}, len(args))
|
l := make([]interface{}, len(args))
|
||||||
for i, a := range args {
|
for i, a := range args {
|
||||||
|
@ -533,16 +531,16 @@ func (self *_runtime) convertCallParameter(v Value, t reflect.Type) (reflect.Val
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
r, err := self.convertCallParameter(rv, t.Out(0))
|
r, err := rt.convertCallParameter(rv, t.Out(0))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(self.panicTypeError(err.Error()))
|
panic(rt.panicTypeError("convertCallParameter Func: %s", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
return []reflect.Value{r}
|
return []reflect.Value{r}
|
||||||
}), nil
|
}), nil
|
||||||
}
|
}
|
||||||
case reflect.Struct:
|
case reflect.Struct:
|
||||||
if o := v._object(); o != nil && o.class == classObject {
|
if o := v.object(); o != nil && o.class == classObjectName {
|
||||||
s := reflect.New(t)
|
s := reflect.New(t)
|
||||||
|
|
||||||
for _, k := range o.propertyOrder {
|
for _, k := range o.propertyOrder {
|
||||||
|
@ -570,9 +568,9 @@ func (self *_runtime) convertCallParameter(v Value, t reflect.Type) (reflect.Val
|
||||||
ss = ss.Field(i)
|
ss = ss.Field(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
v, err := self.convertCallParameter(o.get(k), ss.Type())
|
v, err := rt.convertCallParameter(o.get(k), ss.Type())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reflect.Zero(t), fmt.Errorf("couldn't convert property %q of %s: %s", k, t, err.Error())
|
return reflect.Zero(t), fmt.Errorf("couldn't convert property %q of %s: %w", k, t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ss.Set(v)
|
ss.Set(v)
|
||||||
|
@ -583,16 +581,16 @@ func (self *_runtime) convertCallParameter(v Value, t reflect.Type) (reflect.Val
|
||||||
}
|
}
|
||||||
|
|
||||||
if tk == reflect.String {
|
if tk == reflect.String {
|
||||||
if o := v._object(); o != nil && o.hasProperty("toString") {
|
if o := v.object(); o != nil && o.hasProperty("toString") {
|
||||||
if fn := o.get("toString"); fn.IsFunction() {
|
if fn := o.get("toString"); fn.IsFunction() {
|
||||||
sv, err := fn.Call(v)
|
sv, err := fn.Call(v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reflect.Zero(t), fmt.Errorf("couldn't call toString: %s", err.Error())
|
return reflect.Zero(t), fmt.Errorf("couldn't call toString: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
r, err := self.convertCallParameter(sv, t)
|
r, err := rt.convertCallParameter(sv, t)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reflect.Zero(t), fmt.Errorf("couldn't convert toString result: %s", err.Error())
|
return reflect.Zero(t), fmt.Errorf("couldn't convert toString result: %w", err)
|
||||||
}
|
}
|
||||||
return r, nil
|
return r, nil
|
||||||
}
|
}
|
||||||
|
@ -608,7 +606,7 @@ func (self *_runtime) convertCallParameter(v Value, t reflect.Type) (reflect.Val
|
||||||
r := reflect.New(t)
|
r := reflect.New(t)
|
||||||
|
|
||||||
if err := r.Interface().(encoding.TextUnmarshaler).UnmarshalText([]byte(v.string())); err != nil {
|
if err := r.Interface().(encoding.TextUnmarshaler).UnmarshalText([]byte(v.string())); err != nil {
|
||||||
return reflect.Zero(t), fmt.Errorf("can't convert to %s as TextUnmarshaller: %s", t.String(), err.Error())
|
return reflect.Zero(t), fmt.Errorf("can't convert to %s as TextUnmarshaller: %w", t.String(), err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return r.Elem(), nil
|
return r.Elem(), nil
|
||||||
|
@ -634,7 +632,7 @@ func (self *_runtime) convertCallParameter(v Value, t reflect.Type) (reflect.Val
|
||||||
return reflect.Zero(t), fmt.Errorf("can't convert from %q to %q", s, t)
|
return reflect.Zero(t), fmt.Errorf("can't convert from %q to %q", s, t)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_runtime) toValue(value interface{}) Value {
|
func (rt *runtime) toValue(value interface{}) Value {
|
||||||
rv, ok := value.(reflect.Value)
|
rv, ok := value.(reflect.Value)
|
||||||
if ok {
|
if ok {
|
||||||
value = rv.Interface()
|
value = rv.Interface()
|
||||||
|
@ -647,58 +645,57 @@ func (self *_runtime) toValue(value interface{}) Value {
|
||||||
var name, file string
|
var name, file string
|
||||||
var line int
|
var line int
|
||||||
pc := reflect.ValueOf(value).Pointer()
|
pc := reflect.ValueOf(value).Pointer()
|
||||||
fn := runtime.FuncForPC(pc)
|
fn := goruntime.FuncForPC(pc)
|
||||||
if fn != nil {
|
if fn != nil {
|
||||||
name = fn.Name()
|
name = fn.Name()
|
||||||
file, line = fn.FileLine(pc)
|
file, line = fn.FileLine(pc)
|
||||||
file = path.Base(file)
|
file = path.Base(file)
|
||||||
}
|
}
|
||||||
return toValue_object(self.newNativeFunction(name, file, line, value))
|
return objectValue(rt.newNativeFunction(name, file, line, value))
|
||||||
case _nativeFunction:
|
case nativeFunction:
|
||||||
var name, file string
|
var name, file string
|
||||||
var line int
|
var line int
|
||||||
pc := reflect.ValueOf(value).Pointer()
|
pc := reflect.ValueOf(value).Pointer()
|
||||||
fn := runtime.FuncForPC(pc)
|
fn := goruntime.FuncForPC(pc)
|
||||||
if fn != nil {
|
if fn != nil {
|
||||||
name = fn.Name()
|
name = fn.Name()
|
||||||
file, line = fn.FileLine(pc)
|
file, line = fn.FileLine(pc)
|
||||||
file = path.Base(file)
|
file = path.Base(file)
|
||||||
}
|
}
|
||||||
return toValue_object(self.newNativeFunction(name, file, line, value))
|
return objectValue(rt.newNativeFunction(name, file, line, value))
|
||||||
case Object, *Object, _object, *_object:
|
case Object, *Object, object, *object:
|
||||||
// Nothing happens.
|
// Nothing happens.
|
||||||
// FIXME We should really figure out what can come here.
|
// FIXME We should really figure out what can come here.
|
||||||
// This catch-all is ugly.
|
// This catch-all is ugly.
|
||||||
default:
|
default:
|
||||||
{
|
val := reflect.ValueOf(value)
|
||||||
value := reflect.ValueOf(value)
|
if ok && val.Kind() == rv.Kind() {
|
||||||
if ok && value.Kind() == rv.Kind() {
|
|
||||||
// Use passed in rv which may be writable.
|
// Use passed in rv which may be writable.
|
||||||
value = rv
|
val = rv
|
||||||
}
|
}
|
||||||
|
|
||||||
switch value.Kind() {
|
switch val.Kind() {
|
||||||
case reflect.Ptr:
|
case reflect.Ptr:
|
||||||
switch reflect.Indirect(value).Kind() {
|
switch reflect.Indirect(val).Kind() {
|
||||||
case reflect.Struct:
|
case reflect.Struct:
|
||||||
return toValue_object(self.newGoStructObject(value))
|
return objectValue(rt.newGoStructObject(val))
|
||||||
case reflect.Array:
|
case reflect.Array:
|
||||||
return toValue_object(self.newGoArray(value))
|
return objectValue(rt.newGoArray(val))
|
||||||
}
|
}
|
||||||
case reflect.Struct:
|
case reflect.Struct:
|
||||||
return toValue_object(self.newGoStructObject(value))
|
return objectValue(rt.newGoStructObject(val))
|
||||||
case reflect.Map:
|
case reflect.Map:
|
||||||
return toValue_object(self.newGoMapObject(value))
|
return objectValue(rt.newGoMapObject(val))
|
||||||
case reflect.Slice:
|
case reflect.Slice:
|
||||||
return toValue_object(self.newGoSlice(value))
|
return objectValue(rt.newGoSlice(val))
|
||||||
case reflect.Array:
|
case reflect.Array:
|
||||||
return toValue_object(self.newGoArray(value))
|
return objectValue(rt.newGoArray(val))
|
||||||
case reflect.Func:
|
case reflect.Func:
|
||||||
var name, file string
|
var name, file string
|
||||||
var line int
|
var line int
|
||||||
if v := reflect.ValueOf(value); v.Kind() == reflect.Ptr {
|
if v := reflect.ValueOf(val); v.Kind() == reflect.Ptr {
|
||||||
pc := v.Pointer()
|
pc := v.Pointer()
|
||||||
fn := runtime.FuncForPC(pc)
|
fn := goruntime.FuncForPC(pc)
|
||||||
if fn != nil {
|
if fn != nil {
|
||||||
name = fn.Name()
|
name = fn.Name()
|
||||||
file, line = fn.FileLine(pc)
|
file, line = fn.FileLine(pc)
|
||||||
|
@ -706,18 +703,18 @@ func (self *_runtime) toValue(value interface{}) Value {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
typ := value.Type()
|
typ := val.Type()
|
||||||
|
|
||||||
return toValue_object(self.newNativeFunction(name, file, line, func(c FunctionCall) Value {
|
return objectValue(rt.newNativeFunction(name, file, line, func(c FunctionCall) Value {
|
||||||
nargs := typ.NumIn()
|
nargs := typ.NumIn()
|
||||||
|
|
||||||
if len(c.ArgumentList) != nargs {
|
if len(c.ArgumentList) != nargs {
|
||||||
if typ.IsVariadic() {
|
if typ.IsVariadic() {
|
||||||
if len(c.ArgumentList) < nargs-1 {
|
if len(c.ArgumentList) < nargs-1 {
|
||||||
panic(self.panicRangeError(fmt.Sprintf("expected at least %d arguments; got %d", nargs-1, len(c.ArgumentList))))
|
panic(rt.panicRangeError(fmt.Sprintf("expected at least %d arguments; got %d", nargs-1, len(c.ArgumentList))))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
panic(self.panicRangeError(fmt.Sprintf("expected %d argument(s); got %d", nargs, len(c.ArgumentList))))
|
panic(rt.panicRangeError(fmt.Sprintf("expected %d argument(s); got %d", nargs, len(c.ArgumentList))))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -745,16 +742,16 @@ func (self *_runtime) toValue(value interface{}) Value {
|
||||||
// actual set of variadic Go arguments. if that succeeds, break
|
// actual set of variadic Go arguments. if that succeeds, break
|
||||||
// out of the loop.
|
// out of the loop.
|
||||||
if typ.IsVariadic() && len(c.ArgumentList) == nargs && i == nargs-1 {
|
if typ.IsVariadic() && len(c.ArgumentList) == nargs && i == nargs-1 {
|
||||||
if v, err := self.convertCallParameter(a, typ.In(n)); err == nil {
|
if v, err := rt.convertCallParameter(a, typ.In(n)); err == nil {
|
||||||
in[i] = v
|
in[i] = v
|
||||||
callSlice = true
|
callSlice = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
v, err := self.convertCallParameter(a, t)
|
v, err := rt.convertCallParameter(a, t)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(self.panicTypeError(err.Error()))
|
panic(rt.panicTypeError(err.Error()))
|
||||||
}
|
}
|
||||||
|
|
||||||
in[i] = v
|
in[i] = v
|
||||||
|
@ -762,58 +759,57 @@ func (self *_runtime) toValue(value interface{}) Value {
|
||||||
|
|
||||||
var out []reflect.Value
|
var out []reflect.Value
|
||||||
if callSlice {
|
if callSlice {
|
||||||
out = value.CallSlice(in)
|
out = val.CallSlice(in)
|
||||||
} else {
|
} else {
|
||||||
out = value.Call(in)
|
out = val.Call(in)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch len(out) {
|
switch len(out) {
|
||||||
case 0:
|
case 0:
|
||||||
return Value{}
|
return Value{}
|
||||||
case 1:
|
case 1:
|
||||||
return self.toValue(out[0].Interface())
|
return rt.toValue(out[0].Interface())
|
||||||
default:
|
default:
|
||||||
s := make([]interface{}, len(out))
|
s := make([]interface{}, len(out))
|
||||||
for i, v := range out {
|
for i, v := range out {
|
||||||
s[i] = self.toValue(v.Interface())
|
s[i] = rt.toValue(v.Interface())
|
||||||
}
|
}
|
||||||
|
|
||||||
return self.toValue(s)
|
return rt.toValue(s)
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return toValue(value)
|
return toValue(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (runtime *_runtime) newGoSlice(value reflect.Value) *_object {
|
func (rt *runtime) newGoSlice(value reflect.Value) *object {
|
||||||
self := runtime.newGoSliceObject(value)
|
obj := rt.newGoSliceObject(value)
|
||||||
self.prototype = runtime.global.ArrayPrototype
|
obj.prototype = rt.global.ArrayPrototype
|
||||||
return self
|
return obj
|
||||||
}
|
}
|
||||||
|
|
||||||
func (runtime *_runtime) newGoArray(value reflect.Value) *_object {
|
func (rt *runtime) newGoArray(value reflect.Value) *object {
|
||||||
self := runtime.newGoArrayObject(value)
|
obj := rt.newGoArrayObject(value)
|
||||||
self.prototype = runtime.global.ArrayPrototype
|
obj.prototype = rt.global.ArrayPrototype
|
||||||
return self
|
return obj
|
||||||
}
|
}
|
||||||
|
|
||||||
func (runtime *_runtime) parse(filename string, src, sm interface{}) (*ast.Program, error) {
|
func (rt *runtime) parse(filename string, src, sm interface{}) (*ast.Program, error) {
|
||||||
return parser.ParseFileWithSourceMap(nil, filename, src, sm, 0)
|
return parser.ParseFileWithSourceMap(nil, filename, src, sm, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (runtime *_runtime) cmpl_parse(filename string, src, sm interface{}) (*_nodeProgram, error) {
|
func (rt *runtime) cmplParse(filename string, src, sm interface{}) (*nodeProgram, error) {
|
||||||
program, err := parser.ParseFileWithSourceMap(nil, filename, src, sm, 0)
|
program, err := parser.ParseFileWithSourceMap(nil, filename, src, sm, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return cmpl_parse(program), nil
|
return cmplParse(program), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_runtime) parseSource(src, sm interface{}) (*_nodeProgram, *ast.Program, error) {
|
func (rt *runtime) parseSource(src, sm interface{}) (*nodeProgram, *ast.Program, error) {
|
||||||
switch src := src.(type) {
|
switch src := src.(type) {
|
||||||
case *ast.Program:
|
case *ast.Program:
|
||||||
return nil, src, nil
|
return nil, src, nil
|
||||||
|
@ -821,22 +817,22 @@ func (self *_runtime) parseSource(src, sm interface{}) (*_nodeProgram, *ast.Prog
|
||||||
return src.program, nil, nil
|
return src.program, nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
program, err := self.parse("", src, sm)
|
program, err := rt.parse("", src, sm)
|
||||||
|
|
||||||
return nil, program, err
|
return nil, program, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_runtime) cmpl_runOrEval(src, sm interface{}, eval bool) (Value, error) {
|
func (rt *runtime) cmplRunOrEval(src, sm interface{}, eval bool) (Value, error) {
|
||||||
result := Value{}
|
result := Value{}
|
||||||
cmpl_program, program, err := self.parseSource(src, sm)
|
node, program, err := rt.parseSource(src, sm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
if cmpl_program == nil {
|
if node == nil {
|
||||||
cmpl_program = cmpl_parse(program)
|
node = cmplParse(program)
|
||||||
}
|
}
|
||||||
err = catchPanic(func() {
|
err = catchPanic(func() {
|
||||||
result = self.cmpl_evaluate_nodeProgram(cmpl_program, eval)
|
result = rt.cmplEvaluateNodeProgram(node, eval)
|
||||||
})
|
})
|
||||||
switch result.kind {
|
switch result.kind {
|
||||||
case valueEmpty:
|
case valueEmpty:
|
||||||
|
@ -847,33 +843,32 @@ func (self *_runtime) cmpl_runOrEval(src, sm interface{}, eval bool) (Value, err
|
||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_runtime) cmpl_run(src, sm interface{}) (Value, error) {
|
func (rt *runtime) cmplRun(src, sm interface{}) (Value, error) {
|
||||||
return self.cmpl_runOrEval(src, sm, false)
|
return rt.cmplRunOrEval(src, sm, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_runtime) cmpl_eval(src, sm interface{}) (Value, error) {
|
func (rt *runtime) cmplEval(src, sm interface{}) (Value, error) {
|
||||||
return self.cmpl_runOrEval(src, sm, true)
|
return rt.cmplRunOrEval(src, sm, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_runtime) parseThrow(err error) {
|
func (rt *runtime) parseThrow(err error) {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
switch err := err.(type) {
|
|
||||||
case parser.ErrorList:
|
var errl parser.ErrorList
|
||||||
{
|
if errors.Is(err, &errl) {
|
||||||
err := err[0]
|
err := errl[0]
|
||||||
if err.Message == "Invalid left-hand side in assignment" {
|
if err.Message == "invalid left-hand side in assignment" {
|
||||||
panic(self.panicReferenceError(err.Message))
|
panic(rt.panicReferenceError(err.Message))
|
||||||
}
|
}
|
||||||
panic(self.panicSyntaxError(err.Message))
|
panic(rt.panicSyntaxError(err.Message))
|
||||||
}
|
}
|
||||||
}
|
panic(rt.panicSyntaxError(err.Error()))
|
||||||
panic(self.panicSyntaxError(err.Error()))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_runtime) cmpl_parseOrThrow(src, sm interface{}) *_nodeProgram {
|
func (rt *runtime) cmplParseOrThrow(src, sm interface{}) *nodeProgram {
|
||||||
program, err := self.cmpl_parse("", src, sm)
|
program, err := rt.cmplParse("", src, sm)
|
||||||
self.parseThrow(err) // Will panic/throw appropriately
|
rt.parseThrow(err) // Will panic/throw appropriately
|
||||||
return program
|
return program
|
||||||
}
|
}
|
||||||
|
|
32
v1/vendor/github.com/robertkrimen/otto/scope.go
generated
vendored
|
@ -1,33 +1,19 @@
|
||||||
package otto
|
package otto
|
||||||
|
|
||||||
// _scope:
|
// An ECMA-262 ExecutionContext.
|
||||||
// entryFile
|
type scope struct {
|
||||||
// entryIdx
|
lexical stasher
|
||||||
// top?
|
variable stasher
|
||||||
// outer => nil
|
this *object
|
||||||
|
|
||||||
// _stash:
|
|
||||||
// lexical
|
|
||||||
// variable
|
|
||||||
//
|
|
||||||
// _thisStash (ObjectEnvironment)
|
|
||||||
// _fnStash
|
|
||||||
// _dclStash
|
|
||||||
|
|
||||||
// An ECMA-262 ExecutionContext
|
|
||||||
type _scope struct {
|
|
||||||
lexical _stash
|
|
||||||
variable _stash
|
|
||||||
this *_object
|
|
||||||
eval bool // Replace this with kind?
|
eval bool // Replace this with kind?
|
||||||
outer *_scope
|
outer *scope
|
||||||
depth int
|
depth int
|
||||||
|
|
||||||
frame _frame
|
frame frame
|
||||||
}
|
}
|
||||||
|
|
||||||
func newScope(lexical _stash, variable _stash, this *_object) *_scope {
|
func newScope(lexical stasher, variable stasher, this *object) *scope {
|
||||||
return &_scope{
|
return &scope{
|
||||||
lexical: lexical,
|
lexical: lexical,
|
||||||
variable: variable,
|
variable: variable,
|
||||||
this: this,
|
this: this,
|
||||||
|
|
50
v1/vendor/github.com/robertkrimen/otto/script.go
generated
vendored
|
@ -6,6 +6,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ErrVersion is an error which represents a version mismatch.
|
||||||
var ErrVersion = errors.New("version mismatch")
|
var ErrVersion = errors.New("version mismatch")
|
||||||
|
|
||||||
var scriptVersion = "2014-04-13/1"
|
var scriptVersion = "2014-04-13/1"
|
||||||
|
@ -14,7 +15,7 @@ var scriptVersion = "2014-04-13/1"
|
||||||
// Passing a Script value to a run method will evaluate the JavaScript.
|
// Passing a Script value to a run method will evaluate the JavaScript.
|
||||||
type Script struct {
|
type Script struct {
|
||||||
version string
|
version string
|
||||||
program *_nodeProgram
|
program *nodeProgram
|
||||||
filename string
|
filename string
|
||||||
src string
|
src string
|
||||||
}
|
}
|
||||||
|
@ -24,23 +25,22 @@ type Script struct {
|
||||||
//
|
//
|
||||||
// script, err := vm.Compile("", `var abc; if (!abc) abc = 0; abc += 2; abc;`)
|
// script, err := vm.Compile("", `var abc; if (!abc) abc = 0; abc += 2; abc;`)
|
||||||
// vm.Run(script)
|
// vm.Run(script)
|
||||||
func (self *Otto) Compile(filename string, src interface{}) (*Script, error) {
|
func (o *Otto) Compile(filename string, src interface{}) (*Script, error) {
|
||||||
return self.CompileWithSourceMap(filename, src, nil)
|
return o.CompileWithSourceMap(filename, src, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CompileWithSourceMap does the same thing as Compile, but with the obvious
|
// CompileWithSourceMap does the same thing as Compile, but with the obvious
|
||||||
// difference of applying a source map.
|
// difference of applying a source map.
|
||||||
func (self *Otto) CompileWithSourceMap(filename string, src, sm interface{}) (*Script, error) {
|
func (o *Otto) CompileWithSourceMap(filename string, src, sm interface{}) (*Script, error) {
|
||||||
program, err := self.runtime.parse(filename, src, sm)
|
program, err := o.runtime.parse(filename, src, sm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
cmpl_program := cmpl_parse(program)
|
node := cmplParse(program)
|
||||||
|
|
||||||
script := &Script{
|
script := &Script{
|
||||||
version: scriptVersion,
|
version: scriptVersion,
|
||||||
program: cmpl_program,
|
program: node,
|
||||||
filename: filename,
|
filename: filename,
|
||||||
src: program.File.Source(),
|
src: program.File.Source(),
|
||||||
}
|
}
|
||||||
|
@ -48,30 +48,30 @@ func (self *Otto) CompileWithSourceMap(filename string, src, sm interface{}) (*S
|
||||||
return script, nil
|
return script, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *Script) String() string {
|
func (s *Script) String() string {
|
||||||
return "// " + self.filename + "\n" + self.src
|
return "// " + s.filename + "\n" + s.src
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarshalBinary will marshal a script into a binary form. A marshalled script
|
// MarshalBinary will marshal a script into a binary form. A marshalled script
|
||||||
// that is later unmarshalled can be executed on the same version of the otto runtime.
|
// that is later unmarshalled can be executed on the same version of the otto runtime.
|
||||||
//
|
//
|
||||||
// The binary format can change at any time and should be considered unspecified and opaque.
|
// The binary format can change at any time and should be considered unspecified and opaque.
|
||||||
func (self *Script) marshalBinary() ([]byte, error) {
|
func (s *Script) marshalBinary() ([]byte, error) {
|
||||||
var bfr bytes.Buffer
|
var bfr bytes.Buffer
|
||||||
encoder := gob.NewEncoder(&bfr)
|
encoder := gob.NewEncoder(&bfr)
|
||||||
err := encoder.Encode(self.version)
|
err := encoder.Encode(s.version)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
err = encoder.Encode(self.program)
|
err = encoder.Encode(s.program)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
err = encoder.Encode(self.filename)
|
err = encoder.Encode(s.filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
err = encoder.Encode(self.src)
|
err = encoder.Encode(s.src)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -83,27 +83,27 @@ func (self *Script) marshalBinary() ([]byte, error) {
|
||||||
// will return an error.
|
// will return an error.
|
||||||
//
|
//
|
||||||
// The binary format can change at any time and should be considered unspecified and opaque.
|
// The binary format can change at any time and should be considered unspecified and opaque.
|
||||||
func (self *Script) unmarshalBinary(data []byte) (err error) {
|
func (s *Script) unmarshalBinary(data []byte) (err error) { //nolint: nonamedreturns
|
||||||
decoder := gob.NewDecoder(bytes.NewReader(data))
|
decoder := gob.NewDecoder(bytes.NewReader(data))
|
||||||
defer func() {
|
defer func() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
self.version = ""
|
s.version = ""
|
||||||
self.program = nil
|
s.program = nil
|
||||||
self.filename = ""
|
s.filename = ""
|
||||||
self.src = ""
|
s.src = ""
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
if err = decoder.Decode(&self.version); err != nil {
|
if err = decoder.Decode(&s.version); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if self.version != scriptVersion {
|
if s.version != scriptVersion {
|
||||||
return ErrVersion
|
return ErrVersion
|
||||||
}
|
}
|
||||||
if err = decoder.Decode(&self.program); err != nil {
|
if err = decoder.Decode(&s.program); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err = decoder.Decode(&self.filename); err != nil {
|
if err = decoder.Decode(&s.filename); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return decoder.Decode(&self.src)
|
return decoder.Decode(&s.src)
|
||||||
}
|
}
|
||||||
|
|
263
v1/vendor/github.com/robertkrimen/otto/stash.go
generated
vendored
|
@ -4,11 +4,8 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ======
|
// stasher is implemented by types which can stash data.
|
||||||
// _stash
|
type stasher interface {
|
||||||
// ======
|
|
||||||
|
|
||||||
type _stash interface {
|
|
||||||
hasBinding(string) bool //
|
hasBinding(string) bool //
|
||||||
createBinding(string, bool, Value) // CreateMutableBinding
|
createBinding(string, bool, Value) // CreateMutableBinding
|
||||||
setBinding(string, Value, bool) // SetMutableBinding
|
setBinding(string, Value, bool) // SetMutableBinding
|
||||||
|
@ -16,160 +13,151 @@ type _stash interface {
|
||||||
deleteBinding(string) bool //
|
deleteBinding(string) bool //
|
||||||
setValue(string, Value, bool) // createBinding + setBinding
|
setValue(string, Value, bool) // createBinding + setBinding
|
||||||
|
|
||||||
outer() _stash
|
outer() stasher
|
||||||
runtime() *_runtime
|
runtime() *runtime
|
||||||
|
|
||||||
newReference(string, bool, _at) _reference
|
newReference(string, bool, at) referencer
|
||||||
|
|
||||||
clone(clone *_clone) _stash
|
clone(*cloner) stasher
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==========
|
type objectStash struct {
|
||||||
// _objectStash
|
rt *runtime
|
||||||
// ==========
|
outr stasher
|
||||||
|
object *object
|
||||||
type _objectStash struct {
|
|
||||||
_runtime *_runtime
|
|
||||||
_outer _stash
|
|
||||||
object *_object
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_objectStash) runtime() *_runtime {
|
func (s *objectStash) runtime() *runtime {
|
||||||
return self._runtime
|
return s.rt
|
||||||
}
|
}
|
||||||
|
|
||||||
func (runtime *_runtime) newObjectStash(object *_object, outer _stash) *_objectStash {
|
func (rt *runtime) newObjectStash(obj *object, outer stasher) *objectStash {
|
||||||
if object == nil {
|
if obj == nil {
|
||||||
object = runtime.newBaseObject()
|
obj = rt.newBaseObject()
|
||||||
object.class = "environment"
|
obj.class = "environment"
|
||||||
}
|
}
|
||||||
return &_objectStash{
|
return &objectStash{
|
||||||
_runtime: runtime,
|
rt: rt,
|
||||||
_outer: outer,
|
outr: outer,
|
||||||
object: object,
|
object: obj,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (in *_objectStash) clone(clone *_clone) _stash {
|
func (s *objectStash) clone(c *cloner) stasher {
|
||||||
out, exists := clone.objectStash(in)
|
out, exists := c.objectStash(s)
|
||||||
if exists {
|
if exists {
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
*out = _objectStash{
|
*out = objectStash{
|
||||||
clone.runtime,
|
c.runtime,
|
||||||
clone.stash(in._outer),
|
c.stash(s.outr),
|
||||||
clone.object(in.object),
|
c.object(s.object),
|
||||||
}
|
}
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_objectStash) hasBinding(name string) bool {
|
func (s *objectStash) hasBinding(name string) bool {
|
||||||
return self.object.hasProperty(name)
|
return s.object.hasProperty(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_objectStash) createBinding(name string, deletable bool, value Value) {
|
func (s *objectStash) createBinding(name string, deletable bool, value Value) {
|
||||||
if self.object.hasProperty(name) {
|
if s.object.hasProperty(name) {
|
||||||
panic(hereBeDragons())
|
panic(hereBeDragons())
|
||||||
}
|
}
|
||||||
mode := _propertyMode(0111)
|
mode := propertyMode(0o111)
|
||||||
if !deletable {
|
if !deletable {
|
||||||
mode = _propertyMode(0110)
|
mode = propertyMode(0o110)
|
||||||
}
|
}
|
||||||
// TODO False?
|
// TODO False?
|
||||||
self.object.defineProperty(name, value, mode, false)
|
s.object.defineProperty(name, value, mode, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_objectStash) setBinding(name string, value Value, strict bool) {
|
func (s *objectStash) setBinding(name string, value Value, strict bool) {
|
||||||
self.object.put(name, value, strict)
|
s.object.put(name, value, strict)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_objectStash) setValue(name string, value Value, throw bool) {
|
func (s *objectStash) setValue(name string, value Value, throw bool) {
|
||||||
if !self.hasBinding(name) {
|
if !s.hasBinding(name) {
|
||||||
self.createBinding(name, true, value) // Configurable by default
|
s.createBinding(name, true, value) // Configurable by default
|
||||||
} else {
|
} else {
|
||||||
self.setBinding(name, value, throw)
|
s.setBinding(name, value, throw)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_objectStash) getBinding(name string, throw bool) Value {
|
func (s *objectStash) getBinding(name string, throw bool) Value {
|
||||||
if self.object.hasProperty(name) {
|
if s.object.hasProperty(name) {
|
||||||
return self.object.get(name)
|
return s.object.get(name)
|
||||||
}
|
}
|
||||||
if throw { // strict?
|
if throw { // strict?
|
||||||
panic(self._runtime.panicReferenceError("Not Defined", name))
|
panic(s.rt.panicReferenceError("Not Defined", name))
|
||||||
}
|
}
|
||||||
return Value{}
|
return Value{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_objectStash) deleteBinding(name string) bool {
|
func (s *objectStash) deleteBinding(name string) bool {
|
||||||
return self.object.delete(name, false)
|
return s.object.delete(name, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_objectStash) outer() _stash {
|
func (s *objectStash) outer() stasher {
|
||||||
return self._outer
|
return s.outr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_objectStash) newReference(name string, strict bool, at _at) _reference {
|
func (s *objectStash) newReference(name string, strict bool, atv at) referencer {
|
||||||
return newPropertyReference(self._runtime, self.object, name, strict, at)
|
return newPropertyReference(s.rt, s.object, name, strict, atv)
|
||||||
}
|
}
|
||||||
|
|
||||||
// =========
|
type dclStash struct {
|
||||||
// _dclStash
|
rt *runtime
|
||||||
// =========
|
outr stasher
|
||||||
|
property map[string]dclProperty
|
||||||
type _dclStash struct {
|
|
||||||
_runtime *_runtime
|
|
||||||
_outer _stash
|
|
||||||
property map[string]_dclProperty
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type _dclProperty struct {
|
type dclProperty struct {
|
||||||
value Value
|
value Value
|
||||||
mutable bool
|
mutable bool
|
||||||
deletable bool
|
deletable bool
|
||||||
readable bool
|
readable bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (runtime *_runtime) newDeclarationStash(outer _stash) *_dclStash {
|
func (rt *runtime) newDeclarationStash(outer stasher) *dclStash {
|
||||||
return &_dclStash{
|
return &dclStash{
|
||||||
_runtime: runtime,
|
rt: rt,
|
||||||
_outer: outer,
|
outr: outer,
|
||||||
property: map[string]_dclProperty{},
|
property: map[string]dclProperty{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (in *_dclStash) clone(clone *_clone) _stash {
|
func (s *dclStash) clone(c *cloner) stasher {
|
||||||
out, exists := clone.dclStash(in)
|
out, exists := c.dclStash(s)
|
||||||
if exists {
|
if exists {
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
property := make(map[string]_dclProperty, len(in.property))
|
prop := make(map[string]dclProperty, len(s.property))
|
||||||
for index, value := range in.property {
|
for index, value := range s.property {
|
||||||
property[index] = clone.dclProperty(value)
|
prop[index] = c.dclProperty(value)
|
||||||
}
|
}
|
||||||
*out = _dclStash{
|
*out = dclStash{
|
||||||
clone.runtime,
|
c.runtime,
|
||||||
clone.stash(in._outer),
|
c.stash(s.outr),
|
||||||
property,
|
prop,
|
||||||
}
|
}
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_dclStash) hasBinding(name string) bool {
|
func (s *dclStash) hasBinding(name string) bool {
|
||||||
_, exists := self.property[name]
|
_, exists := s.property[name]
|
||||||
return exists
|
return exists
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_dclStash) runtime() *_runtime {
|
func (s *dclStash) runtime() *runtime {
|
||||||
return self._runtime
|
return s.rt
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_dclStash) createBinding(name string, deletable bool, value Value) {
|
func (s *dclStash) createBinding(name string, deletable bool, value Value) {
|
||||||
_, exists := self.property[name]
|
if _, exists := s.property[name]; exists {
|
||||||
if exists {
|
|
||||||
panic(fmt.Errorf("createBinding: %s: already exists", name))
|
panic(fmt.Errorf("createBinding: %s: already exists", name))
|
||||||
}
|
}
|
||||||
self.property[name] = _dclProperty{
|
s.property[name] = dclProperty{
|
||||||
value: value,
|
value: value,
|
||||||
mutable: true,
|
mutable: true,
|
||||||
deletable: deletable,
|
deletable: deletable,
|
||||||
|
@ -177,62 +165,62 @@ func (self *_dclStash) createBinding(name string, deletable bool, value Value) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_dclStash) setBinding(name string, value Value, strict bool) {
|
func (s *dclStash) setBinding(name string, value Value, strict bool) {
|
||||||
property, exists := self.property[name]
|
prop, exists := s.property[name]
|
||||||
if !exists {
|
if !exists {
|
||||||
panic(fmt.Errorf("setBinding: %s: missing", name))
|
panic(fmt.Errorf("setBinding: %s: missing", name))
|
||||||
}
|
}
|
||||||
if property.mutable {
|
if prop.mutable {
|
||||||
property.value = value
|
prop.value = value
|
||||||
self.property[name] = property
|
s.property[name] = prop
|
||||||
} else {
|
} else {
|
||||||
self._runtime.typeErrorResult(strict)
|
s.rt.typeErrorResult(strict)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_dclStash) setValue(name string, value Value, throw bool) {
|
func (s *dclStash) setValue(name string, value Value, throw bool) {
|
||||||
if !self.hasBinding(name) {
|
if !s.hasBinding(name) {
|
||||||
self.createBinding(name, false, value) // NOT deletable by default
|
s.createBinding(name, false, value) // NOT deletable by default
|
||||||
} else {
|
} else {
|
||||||
self.setBinding(name, value, throw)
|
s.setBinding(name, value, throw)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME This is called a __lot__
|
// FIXME This is called a __lot__.
|
||||||
func (self *_dclStash) getBinding(name string, throw bool) Value {
|
func (s *dclStash) getBinding(name string, throw bool) Value {
|
||||||
property, exists := self.property[name]
|
prop, exists := s.property[name]
|
||||||
if !exists {
|
if !exists {
|
||||||
panic(fmt.Errorf("getBinding: %s: missing", name))
|
panic(fmt.Errorf("getBinding: %s: missing", name))
|
||||||
}
|
}
|
||||||
if !property.mutable && !property.readable {
|
if !prop.mutable && !prop.readable {
|
||||||
if throw { // strict?
|
if throw { // strict?
|
||||||
panic(self._runtime.panicTypeError())
|
panic(s.rt.panicTypeError("getBinding property %s not mutable and not readable", name))
|
||||||
}
|
}
|
||||||
return Value{}
|
return Value{}
|
||||||
}
|
}
|
||||||
return property.value
|
return prop.value
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_dclStash) deleteBinding(name string) bool {
|
func (s *dclStash) deleteBinding(name string) bool {
|
||||||
property, exists := self.property[name]
|
prop, exists := s.property[name]
|
||||||
if !exists {
|
if !exists {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if !property.deletable {
|
if !prop.deletable {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
delete(self.property, name)
|
delete(s.property, name)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_dclStash) outer() _stash {
|
func (s *dclStash) outer() stasher {
|
||||||
return self._outer
|
return s.outr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_dclStash) newReference(name string, strict bool, _ _at) _reference {
|
func (s *dclStash) newReference(name string, strict bool, _ at) referencer {
|
||||||
return &_stashReference{
|
return &stashReference{
|
||||||
name: name,
|
name: name,
|
||||||
base: self,
|
base: s,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -240,57 +228,62 @@ func (self *_dclStash) newReference(name string, strict bool, _ _at) _reference
|
||||||
// _fnStash
|
// _fnStash
|
||||||
// ========
|
// ========
|
||||||
|
|
||||||
type _fnStash struct {
|
type fnStash struct {
|
||||||
_dclStash
|
dclStash
|
||||||
arguments *_object
|
arguments *object
|
||||||
indexOfArgumentName map[string]string
|
indexOfArgumentName map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (runtime *_runtime) newFunctionStash(outer _stash) *_fnStash {
|
func (rt *runtime) newFunctionStash(outer stasher) *fnStash {
|
||||||
return &_fnStash{
|
return &fnStash{
|
||||||
_dclStash: _dclStash{
|
dclStash: dclStash{
|
||||||
_runtime: runtime,
|
rt: rt,
|
||||||
_outer: outer,
|
outr: outer,
|
||||||
property: map[string]_dclProperty{},
|
property: map[string]dclProperty{},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (in *_fnStash) clone(clone *_clone) _stash {
|
func (s *fnStash) clone(c *cloner) stasher {
|
||||||
out, exists := clone.fnStash(in)
|
out, exists := c.fnStash(s)
|
||||||
if exists {
|
if exists {
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
dclStash := in._dclStash.clone(clone).(*_dclStash)
|
dclStash := s.dclStash.clone(c).(*dclStash)
|
||||||
index := make(map[string]string, len(in.indexOfArgumentName))
|
index := make(map[string]string, len(s.indexOfArgumentName))
|
||||||
for name, value := range in.indexOfArgumentName {
|
for name, value := range s.indexOfArgumentName {
|
||||||
index[name] = value
|
index[name] = value
|
||||||
}
|
}
|
||||||
*out = _fnStash{
|
*out = fnStash{
|
||||||
_dclStash: *dclStash,
|
dclStash: *dclStash,
|
||||||
arguments: clone.object(in.arguments),
|
arguments: c.object(s.arguments),
|
||||||
indexOfArgumentName: index,
|
indexOfArgumentName: index,
|
||||||
}
|
}
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
func getStashProperties(stash _stash) (keys []string) {
|
// getStashProperties returns the properties from stash.
|
||||||
|
func getStashProperties(stash stasher) []string {
|
||||||
switch vars := stash.(type) {
|
switch vars := stash.(type) {
|
||||||
case *_dclStash:
|
case *dclStash:
|
||||||
|
keys := make([]string, 0, len(vars.property))
|
||||||
for k := range vars.property {
|
for k := range vars.property {
|
||||||
keys = append(keys, k)
|
keys = append(keys, k)
|
||||||
}
|
}
|
||||||
case *_fnStash:
|
return keys
|
||||||
|
case *fnStash:
|
||||||
|
keys := make([]string, 0, len(vars.property))
|
||||||
for k := range vars.property {
|
for k := range vars.property {
|
||||||
keys = append(keys, k)
|
keys = append(keys, k)
|
||||||
}
|
}
|
||||||
case *_objectStash:
|
return keys
|
||||||
|
case *objectStash:
|
||||||
|
keys := make([]string, 0, len(vars.object.property))
|
||||||
for k := range vars.object.property {
|
for k := range vars.object.property {
|
||||||
keys = append(keys, k)
|
keys = append(keys, k)
|
||||||
}
|
}
|
||||||
|
return keys
|
||||||
default:
|
default:
|
||||||
panic("unknown stash type")
|
panic("unknown stash type")
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
2
v1/vendor/github.com/robertkrimen/otto/token/Makefile
generated
vendored
|
@ -1,2 +0,0 @@
|
||||||
token_const.go: tokenfmt
|
|
||||||
./$^ | gofmt > $@
|
|
171
v1/vendor/github.com/robertkrimen/otto/token/README.markdown
generated
vendored
|
@ -1,171 +0,0 @@
|
||||||
# token
|
|
||||||
--
|
|
||||||
import "github.com/robertkrimen/otto/token"
|
|
||||||
|
|
||||||
Package token defines constants representing the lexical tokens of JavaScript
|
|
||||||
(ECMA5).
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
```go
|
|
||||||
const (
|
|
||||||
ILLEGAL
|
|
||||||
EOF
|
|
||||||
COMMENT
|
|
||||||
KEYWORD
|
|
||||||
|
|
||||||
STRING
|
|
||||||
BOOLEAN
|
|
||||||
NULL
|
|
||||||
NUMBER
|
|
||||||
IDENTIFIER
|
|
||||||
|
|
||||||
PLUS // +
|
|
||||||
MINUS // -
|
|
||||||
MULTIPLY // *
|
|
||||||
SLASH // /
|
|
||||||
REMAINDER // %
|
|
||||||
|
|
||||||
AND // &
|
|
||||||
OR // |
|
|
||||||
EXCLUSIVE_OR // ^
|
|
||||||
SHIFT_LEFT // <<
|
|
||||||
SHIFT_RIGHT // >>
|
|
||||||
UNSIGNED_SHIFT_RIGHT // >>>
|
|
||||||
AND_NOT // &^
|
|
||||||
|
|
||||||
ADD_ASSIGN // +=
|
|
||||||
SUBTRACT_ASSIGN // -=
|
|
||||||
MULTIPLY_ASSIGN // *=
|
|
||||||
QUOTIENT_ASSIGN // /=
|
|
||||||
REMAINDER_ASSIGN // %=
|
|
||||||
|
|
||||||
AND_ASSIGN // &=
|
|
||||||
OR_ASSIGN // |=
|
|
||||||
EXCLUSIVE_OR_ASSIGN // ^=
|
|
||||||
SHIFT_LEFT_ASSIGN // <<=
|
|
||||||
SHIFT_RIGHT_ASSIGN // >>=
|
|
||||||
UNSIGNED_SHIFT_RIGHT_ASSIGN // >>>=
|
|
||||||
AND_NOT_ASSIGN // &^=
|
|
||||||
|
|
||||||
LOGICAL_AND // &&
|
|
||||||
LOGICAL_OR // ||
|
|
||||||
INCREMENT // ++
|
|
||||||
DECREMENT // --
|
|
||||||
|
|
||||||
EQUAL // ==
|
|
||||||
STRICT_EQUAL // ===
|
|
||||||
LESS // <
|
|
||||||
GREATER // >
|
|
||||||
ASSIGN // =
|
|
||||||
NOT // !
|
|
||||||
|
|
||||||
BITWISE_NOT // ~
|
|
||||||
|
|
||||||
NOT_EQUAL // !=
|
|
||||||
STRICT_NOT_EQUAL // !==
|
|
||||||
LESS_OR_EQUAL // <=
|
|
||||||
GREATER_OR_EQUAL // >=
|
|
||||||
|
|
||||||
LEFT_PARENTHESIS // (
|
|
||||||
LEFT_BRACKET // [
|
|
||||||
LEFT_BRACE // {
|
|
||||||
COMMA // ,
|
|
||||||
PERIOD // .
|
|
||||||
|
|
||||||
RIGHT_PARENTHESIS // )
|
|
||||||
RIGHT_BRACKET // ]
|
|
||||||
RIGHT_BRACE // }
|
|
||||||
SEMICOLON // ;
|
|
||||||
COLON // :
|
|
||||||
QUESTION_MARK // ?
|
|
||||||
|
|
||||||
IF
|
|
||||||
IN
|
|
||||||
DO
|
|
||||||
|
|
||||||
VAR
|
|
||||||
FOR
|
|
||||||
NEW
|
|
||||||
TRY
|
|
||||||
|
|
||||||
THIS
|
|
||||||
ELSE
|
|
||||||
CASE
|
|
||||||
VOID
|
|
||||||
WITH
|
|
||||||
|
|
||||||
WHILE
|
|
||||||
BREAK
|
|
||||||
CATCH
|
|
||||||
THROW
|
|
||||||
|
|
||||||
RETURN
|
|
||||||
TYPEOF
|
|
||||||
DELETE
|
|
||||||
SWITCH
|
|
||||||
|
|
||||||
DEFAULT
|
|
||||||
FINALLY
|
|
||||||
|
|
||||||
FUNCTION
|
|
||||||
CONTINUE
|
|
||||||
DEBUGGER
|
|
||||||
|
|
||||||
INSTANCEOF
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
#### type Token
|
|
||||||
|
|
||||||
```go
|
|
||||||
type Token int
|
|
||||||
```
|
|
||||||
|
|
||||||
Token is the set of lexical tokens in JavaScript (ECMA5).
|
|
||||||
|
|
||||||
#### func IsKeyword
|
|
||||||
|
|
||||||
```go
|
|
||||||
func IsKeyword(literal string) (Token, bool)
|
|
||||||
```
|
|
||||||
IsKeyword returns the keyword token if literal is a keyword, a KEYWORD token if
|
|
||||||
the literal is a future keyword (const, let, class, super, ...), or 0 if the
|
|
||||||
literal is not a keyword.
|
|
||||||
|
|
||||||
If the literal is a keyword, IsKeyword returns a second value indicating if the
|
|
||||||
literal is considered a future keyword in strict-mode only.
|
|
||||||
|
|
||||||
7.6.1.2 Future Reserved Words:
|
|
||||||
|
|
||||||
const
|
|
||||||
class
|
|
||||||
enum
|
|
||||||
export
|
|
||||||
extends
|
|
||||||
import
|
|
||||||
super
|
|
||||||
|
|
||||||
7.6.1.2 Future Reserved Words (strict):
|
|
||||||
|
|
||||||
implements
|
|
||||||
interface
|
|
||||||
let
|
|
||||||
package
|
|
||||||
private
|
|
||||||
protected
|
|
||||||
public
|
|
||||||
static
|
|
||||||
|
|
||||||
#### func (Token) String
|
|
||||||
|
|
||||||
```go
|
|
||||||
func (tkn Token) String() string
|
|
||||||
```
|
|
||||||
String returns the string corresponding to the token. For operators, delimiters,
|
|
||||||
and keywords the string is the actual token string (e.g., for the token PLUS,
|
|
||||||
the String() is "+"). For all other tokens the string corresponds to the token
|
|
||||||
name (e.g. for the token IDENTIFIER, the string is "IDENTIFIER").
|
|
||||||
|
|
||||||
--
|
|
||||||
**godocdown** http://github.com/robertkrimen/godocdown
|
|
3
v1/vendor/github.com/robertkrimen/otto/token/generate.go
generated
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
package token
|
||||||
|
|
||||||
|
//go:generate go run ../tools/gen-tokens -output token_const.go
|
56
v1/vendor/github.com/robertkrimen/otto/token/token.go
generated
vendored
|
@ -14,63 +14,17 @@ type Token int
|
||||||
// "+"). For all other tokens the string corresponds to the token
|
// "+"). For all other tokens the string corresponds to the token
|
||||||
// name (e.g. for the token IDENTIFIER, the string is "IDENTIFIER").
|
// name (e.g. for the token IDENTIFIER, the string is "IDENTIFIER").
|
||||||
func (tkn Token) String() string {
|
func (tkn Token) String() string {
|
||||||
if 0 == tkn {
|
switch {
|
||||||
|
case tkn == 0:
|
||||||
return "UNKNOWN"
|
return "UNKNOWN"
|
||||||
}
|
case tkn < Token(len(token2string)):
|
||||||
if tkn < Token(len(token2string)) {
|
|
||||||
return token2string[tkn]
|
return token2string[tkn]
|
||||||
}
|
default:
|
||||||
return "token(" + strconv.Itoa(int(tkn)) + ")"
|
return "token(" + strconv.Itoa(int(tkn)) + ")"
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is not used for anything
|
|
||||||
func (tkn Token) precedence(in bool) int {
|
|
||||||
switch tkn {
|
|
||||||
case LOGICAL_OR:
|
|
||||||
return 1
|
|
||||||
|
|
||||||
case LOGICAL_AND:
|
|
||||||
return 2
|
|
||||||
|
|
||||||
case OR, OR_ASSIGN:
|
|
||||||
return 3
|
|
||||||
|
|
||||||
case EXCLUSIVE_OR:
|
|
||||||
return 4
|
|
||||||
|
|
||||||
case AND, AND_ASSIGN, AND_NOT, AND_NOT_ASSIGN:
|
|
||||||
return 5
|
|
||||||
|
|
||||||
case EQUAL,
|
|
||||||
NOT_EQUAL,
|
|
||||||
STRICT_EQUAL,
|
|
||||||
STRICT_NOT_EQUAL:
|
|
||||||
return 6
|
|
||||||
|
|
||||||
case LESS, GREATER, LESS_OR_EQUAL, GREATER_OR_EQUAL, INSTANCEOF:
|
|
||||||
return 7
|
|
||||||
|
|
||||||
case IN:
|
|
||||||
if in {
|
|
||||||
return 7
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
|
|
||||||
case SHIFT_LEFT, SHIFT_RIGHT, UNSIGNED_SHIFT_RIGHT:
|
|
||||||
fallthrough
|
|
||||||
case SHIFT_LEFT_ASSIGN, SHIFT_RIGHT_ASSIGN, UNSIGNED_SHIFT_RIGHT_ASSIGN:
|
|
||||||
return 8
|
|
||||||
|
|
||||||
case PLUS, MINUS, ADD_ASSIGN, SUBTRACT_ASSIGN:
|
|
||||||
return 9
|
|
||||||
|
|
||||||
case MULTIPLY, SLASH, REMAINDER, MULTIPLY_ASSIGN, QUOTIENT_ASSIGN, REMAINDER_ASSIGN:
|
|
||||||
return 11
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type _keyword struct {
|
type keyword struct {
|
||||||
token Token
|
token Token
|
||||||
futureKeyword bool
|
futureKeyword bool
|
||||||
strict bool
|
strict bool
|
||||||
|
|
128
v1/vendor/github.com/robertkrimen/otto/token/token_const.go
generated
vendored
|
@ -1,25 +1,28 @@
|
||||||
|
// Code generated by tools/gen-tokens. DO NOT EDIT.
|
||||||
|
|
||||||
package token
|
package token
|
||||||
|
|
||||||
const (
|
const (
|
||||||
_ Token = iota
|
_ Token = iota
|
||||||
|
|
||||||
|
// Control.
|
||||||
ILLEGAL
|
ILLEGAL
|
||||||
EOF
|
EOF
|
||||||
COMMENT
|
COMMENT
|
||||||
KEYWORD
|
KEYWORD
|
||||||
|
// Types.
|
||||||
STRING
|
STRING
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
NULL
|
NULL
|
||||||
NUMBER
|
NUMBER
|
||||||
IDENTIFIER
|
IDENTIFIER
|
||||||
|
// Maths.
|
||||||
PLUS // +
|
PLUS // +
|
||||||
MINUS // -
|
MINUS // -
|
||||||
MULTIPLY // *
|
MULTIPLY // *
|
||||||
SLASH // /
|
SLASH // /
|
||||||
REMAINDER // %
|
REMAINDER // %
|
||||||
|
// Logical and bitwise operators.
|
||||||
AND // &
|
AND // &
|
||||||
OR // |
|
OR // |
|
||||||
EXCLUSIVE_OR // ^
|
EXCLUSIVE_OR // ^
|
||||||
|
@ -27,13 +30,13 @@ const (
|
||||||
SHIFT_RIGHT // >>
|
SHIFT_RIGHT // >>
|
||||||
UNSIGNED_SHIFT_RIGHT // >>>
|
UNSIGNED_SHIFT_RIGHT // >>>
|
||||||
AND_NOT // &^
|
AND_NOT // &^
|
||||||
|
// Math assignments.
|
||||||
ADD_ASSIGN // +=
|
ADD_ASSIGN // +=
|
||||||
SUBTRACT_ASSIGN // -=
|
SUBTRACT_ASSIGN // -=
|
||||||
MULTIPLY_ASSIGN // *=
|
MULTIPLY_ASSIGN // *=
|
||||||
QUOTIENT_ASSIGN // /=
|
QUOTIENT_ASSIGN // /=
|
||||||
REMAINDER_ASSIGN // %=
|
REMAINDER_ASSIGN // %=
|
||||||
|
// Math and bitwise assignments.
|
||||||
AND_ASSIGN // &=
|
AND_ASSIGN // &=
|
||||||
OR_ASSIGN // |=
|
OR_ASSIGN // |=
|
||||||
EXCLUSIVE_OR_ASSIGN // ^=
|
EXCLUSIVE_OR_ASSIGN // ^=
|
||||||
|
@ -41,74 +44,73 @@ const (
|
||||||
SHIFT_RIGHT_ASSIGN // >>=
|
SHIFT_RIGHT_ASSIGN // >>=
|
||||||
UNSIGNED_SHIFT_RIGHT_ASSIGN // >>>=
|
UNSIGNED_SHIFT_RIGHT_ASSIGN // >>>=
|
||||||
AND_NOT_ASSIGN // &^=
|
AND_NOT_ASSIGN // &^=
|
||||||
|
// Logical operators and decrement / increment.
|
||||||
LOGICAL_AND // &&
|
LOGICAL_AND // &&
|
||||||
LOGICAL_OR // ||
|
LOGICAL_OR // ||
|
||||||
INCREMENT // ++
|
INCREMENT // ++
|
||||||
DECREMENT // --
|
DECREMENT // --
|
||||||
|
// Comparison operators.
|
||||||
EQUAL // ==
|
EQUAL // ==
|
||||||
STRICT_EQUAL // ===
|
STRICT_EQUAL // ===
|
||||||
LESS // <
|
LESS // <
|
||||||
GREATER // >
|
GREATER // >
|
||||||
ASSIGN // =
|
ASSIGN // =
|
||||||
NOT // !
|
NOT // !
|
||||||
|
// Bitwise not.
|
||||||
BITWISE_NOT // ~
|
BITWISE_NOT // ~
|
||||||
|
// Comparison operators.
|
||||||
NOT_EQUAL // !=
|
NOT_EQUAL // !=
|
||||||
STRICT_NOT_EQUAL // !==
|
STRICT_NOT_EQUAL // !==
|
||||||
LESS_OR_EQUAL // <=
|
LESS_OR_EQUAL // <=
|
||||||
GREATER_OR_EQUAL // >=
|
GREATER_OR_EQUAL // >=
|
||||||
|
// Left operators.
|
||||||
LEFT_PARENTHESIS // (
|
LEFT_PARENTHESIS // (
|
||||||
LEFT_BRACKET // [
|
LEFT_BRACKET // [
|
||||||
LEFT_BRACE // {
|
LEFT_BRACE // {
|
||||||
COMMA // ,
|
COMMA // ,
|
||||||
PERIOD // .
|
PERIOD // .
|
||||||
|
// Right operators.
|
||||||
RIGHT_PARENTHESIS // )
|
RIGHT_PARENTHESIS // )
|
||||||
RIGHT_BRACKET // ]
|
RIGHT_BRACKET // ]
|
||||||
RIGHT_BRACE // }
|
RIGHT_BRACE // }
|
||||||
SEMICOLON // ;
|
SEMICOLON // ;
|
||||||
COLON // :
|
COLON // :
|
||||||
QUESTION_MARK // ?
|
QUESTION_MARK // ?
|
||||||
|
// Basic flow - keywords below here.
|
||||||
firstKeyword //nolint: deadcode
|
_
|
||||||
IF
|
IF
|
||||||
IN
|
IN
|
||||||
DO
|
DO
|
||||||
|
// Declarations.
|
||||||
VAR
|
VAR
|
||||||
FOR
|
FOR
|
||||||
NEW
|
NEW
|
||||||
TRY
|
TRY
|
||||||
|
// Advanced flow.
|
||||||
THIS
|
THIS
|
||||||
ELSE
|
ELSE
|
||||||
CASE
|
CASE
|
||||||
VOID
|
VOID
|
||||||
WITH
|
WITH
|
||||||
|
// Loops.
|
||||||
WHILE
|
WHILE
|
||||||
BREAK
|
BREAK
|
||||||
CATCH
|
CATCH
|
||||||
THROW
|
THROW
|
||||||
|
// Functions.
|
||||||
RETURN
|
RETURN
|
||||||
TYPEOF
|
TYPEOF
|
||||||
DELETE
|
DELETE
|
||||||
SWITCH
|
SWITCH
|
||||||
|
// Fallback identifiers.
|
||||||
DEFAULT
|
DEFAULT
|
||||||
FINALLY
|
FINALLY
|
||||||
|
// Miscellaneous.
|
||||||
FUNCTION
|
FUNCTION
|
||||||
CONTINUE
|
CONTINUE
|
||||||
DEBUGGER
|
DEBUGGER
|
||||||
|
// Instance of.
|
||||||
INSTANCEOF
|
INSTANCEOF
|
||||||
lastKeyword //nolint: deadcode
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var token2string = [...]string{
|
var token2string = [...]string{
|
||||||
|
@ -199,149 +201,149 @@ var token2string = [...]string{
|
||||||
INSTANCEOF: "instanceof",
|
INSTANCEOF: "instanceof",
|
||||||
}
|
}
|
||||||
|
|
||||||
var keywordTable = map[string]_keyword{
|
var keywordTable = map[string]keyword{
|
||||||
"if": _keyword{
|
"if": {
|
||||||
token: IF,
|
token: IF,
|
||||||
},
|
},
|
||||||
"in": _keyword{
|
"in": {
|
||||||
token: IN,
|
token: IN,
|
||||||
},
|
},
|
||||||
"do": _keyword{
|
"do": {
|
||||||
token: DO,
|
token: DO,
|
||||||
},
|
},
|
||||||
"var": _keyword{
|
"var": {
|
||||||
token: VAR,
|
token: VAR,
|
||||||
},
|
},
|
||||||
"for": _keyword{
|
"for": {
|
||||||
token: FOR,
|
token: FOR,
|
||||||
},
|
},
|
||||||
"new": _keyword{
|
"new": {
|
||||||
token: NEW,
|
token: NEW,
|
||||||
},
|
},
|
||||||
"try": _keyword{
|
"try": {
|
||||||
token: TRY,
|
token: TRY,
|
||||||
},
|
},
|
||||||
"this": _keyword{
|
"this": {
|
||||||
token: THIS,
|
token: THIS,
|
||||||
},
|
},
|
||||||
"else": _keyword{
|
"else": {
|
||||||
token: ELSE,
|
token: ELSE,
|
||||||
},
|
},
|
||||||
"case": _keyword{
|
"case": {
|
||||||
token: CASE,
|
token: CASE,
|
||||||
},
|
},
|
||||||
"void": _keyword{
|
"void": {
|
||||||
token: VOID,
|
token: VOID,
|
||||||
},
|
},
|
||||||
"with": _keyword{
|
"with": {
|
||||||
token: WITH,
|
token: WITH,
|
||||||
},
|
},
|
||||||
"while": _keyword{
|
"while": {
|
||||||
token: WHILE,
|
token: WHILE,
|
||||||
},
|
},
|
||||||
"break": _keyword{
|
"break": {
|
||||||
token: BREAK,
|
token: BREAK,
|
||||||
},
|
},
|
||||||
"catch": _keyword{
|
"catch": {
|
||||||
token: CATCH,
|
token: CATCH,
|
||||||
},
|
},
|
||||||
"throw": _keyword{
|
"throw": {
|
||||||
token: THROW,
|
token: THROW,
|
||||||
},
|
},
|
||||||
"return": _keyword{
|
"return": {
|
||||||
token: RETURN,
|
token: RETURN,
|
||||||
},
|
},
|
||||||
"typeof": _keyword{
|
"typeof": {
|
||||||
token: TYPEOF,
|
token: TYPEOF,
|
||||||
},
|
},
|
||||||
"delete": _keyword{
|
"delete": {
|
||||||
token: DELETE,
|
token: DELETE,
|
||||||
},
|
},
|
||||||
"switch": _keyword{
|
"switch": {
|
||||||
token: SWITCH,
|
token: SWITCH,
|
||||||
},
|
},
|
||||||
"default": _keyword{
|
"default": {
|
||||||
token: DEFAULT,
|
token: DEFAULT,
|
||||||
},
|
},
|
||||||
"finally": _keyword{
|
"finally": {
|
||||||
token: FINALLY,
|
token: FINALLY,
|
||||||
},
|
},
|
||||||
"function": _keyword{
|
"function": {
|
||||||
token: FUNCTION,
|
token: FUNCTION,
|
||||||
},
|
},
|
||||||
"continue": _keyword{
|
"continue": {
|
||||||
token: CONTINUE,
|
token: CONTINUE,
|
||||||
},
|
},
|
||||||
"debugger": _keyword{
|
"debugger": {
|
||||||
token: DEBUGGER,
|
token: DEBUGGER,
|
||||||
},
|
},
|
||||||
"instanceof": _keyword{
|
"instanceof": {
|
||||||
token: INSTANCEOF,
|
token: INSTANCEOF,
|
||||||
},
|
},
|
||||||
"const": _keyword{
|
"const": {
|
||||||
token: KEYWORD,
|
token: KEYWORD,
|
||||||
futureKeyword: true,
|
futureKeyword: true,
|
||||||
},
|
},
|
||||||
"class": _keyword{
|
"class": {
|
||||||
token: KEYWORD,
|
token: KEYWORD,
|
||||||
futureKeyword: true,
|
futureKeyword: true,
|
||||||
},
|
},
|
||||||
"enum": _keyword{
|
"enum": {
|
||||||
token: KEYWORD,
|
token: KEYWORD,
|
||||||
futureKeyword: true,
|
futureKeyword: true,
|
||||||
},
|
},
|
||||||
"export": _keyword{
|
"export": {
|
||||||
token: KEYWORD,
|
token: KEYWORD,
|
||||||
futureKeyword: true,
|
futureKeyword: true,
|
||||||
},
|
},
|
||||||
"extends": _keyword{
|
"extends": {
|
||||||
token: KEYWORD,
|
token: KEYWORD,
|
||||||
futureKeyword: true,
|
futureKeyword: true,
|
||||||
},
|
},
|
||||||
"import": _keyword{
|
"import": {
|
||||||
token: KEYWORD,
|
token: KEYWORD,
|
||||||
futureKeyword: true,
|
futureKeyword: true,
|
||||||
},
|
},
|
||||||
"super": _keyword{
|
"super": {
|
||||||
token: KEYWORD,
|
token: KEYWORD,
|
||||||
futureKeyword: true,
|
futureKeyword: true,
|
||||||
},
|
},
|
||||||
"implements": _keyword{
|
"implements": {
|
||||||
token: KEYWORD,
|
token: KEYWORD,
|
||||||
futureKeyword: true,
|
futureKeyword: true,
|
||||||
strict: true,
|
strict: true,
|
||||||
},
|
},
|
||||||
"interface": _keyword{
|
"interface": {
|
||||||
token: KEYWORD,
|
token: KEYWORD,
|
||||||
futureKeyword: true,
|
futureKeyword: true,
|
||||||
strict: true,
|
strict: true,
|
||||||
},
|
},
|
||||||
"let": _keyword{
|
"let": {
|
||||||
token: KEYWORD,
|
token: KEYWORD,
|
||||||
futureKeyword: true,
|
futureKeyword: true,
|
||||||
strict: true,
|
strict: true,
|
||||||
},
|
},
|
||||||
"package": _keyword{
|
"package": {
|
||||||
token: KEYWORD,
|
token: KEYWORD,
|
||||||
futureKeyword: true,
|
futureKeyword: true,
|
||||||
strict: true,
|
strict: true,
|
||||||
},
|
},
|
||||||
"private": _keyword{
|
"private": {
|
||||||
token: KEYWORD,
|
token: KEYWORD,
|
||||||
futureKeyword: true,
|
futureKeyword: true,
|
||||||
strict: true,
|
strict: true,
|
||||||
},
|
},
|
||||||
"protected": _keyword{
|
"protected": {
|
||||||
token: KEYWORD,
|
token: KEYWORD,
|
||||||
futureKeyword: true,
|
futureKeyword: true,
|
||||||
strict: true,
|
strict: true,
|
||||||
},
|
},
|
||||||
"public": _keyword{
|
"public": {
|
||||||
token: KEYWORD,
|
token: KEYWORD,
|
||||||
futureKeyword: true,
|
futureKeyword: true,
|
||||||
strict: true,
|
strict: true,
|
||||||
},
|
},
|
||||||
"static": _keyword{
|
"static": {
|
||||||
token: KEYWORD,
|
token: KEYWORD,
|
||||||
futureKeyword: true,
|
futureKeyword: true,
|
||||||
strict: true,
|
strict: true,
|
||||||
|
|
222
v1/vendor/github.com/robertkrimen/otto/token/tokenfmt
generated
vendored
|
@ -1,222 +0,0 @@
|
||||||
#!/usr/bin/env perl
|
|
||||||
|
|
||||||
use strict;
|
|
||||||
use warnings;
|
|
||||||
|
|
||||||
my (%token, @order, @keywords);
|
|
||||||
|
|
||||||
{
|
|
||||||
my $keywords;
|
|
||||||
my @const;
|
|
||||||
push @const, <<_END_;
|
|
||||||
package token
|
|
||||||
|
|
||||||
const(
|
|
||||||
_ Token = iota
|
|
||||||
_END_
|
|
||||||
|
|
||||||
for (split m/\n/, <<_END_) {
|
|
||||||
ILLEGAL
|
|
||||||
EOF
|
|
||||||
COMMENT
|
|
||||||
KEYWORD
|
|
||||||
|
|
||||||
STRING
|
|
||||||
BOOLEAN
|
|
||||||
NULL
|
|
||||||
NUMBER
|
|
||||||
IDENTIFIER
|
|
||||||
|
|
||||||
PLUS +
|
|
||||||
MINUS -
|
|
||||||
MULTIPLY *
|
|
||||||
SLASH /
|
|
||||||
REMAINDER %
|
|
||||||
|
|
||||||
AND &
|
|
||||||
OR |
|
|
||||||
EXCLUSIVE_OR ^
|
|
||||||
SHIFT_LEFT <<
|
|
||||||
SHIFT_RIGHT >>
|
|
||||||
UNSIGNED_SHIFT_RIGHT >>>
|
|
||||||
AND_NOT &^
|
|
||||||
|
|
||||||
ADD_ASSIGN +=
|
|
||||||
SUBTRACT_ASSIGN -=
|
|
||||||
MULTIPLY_ASSIGN *=
|
|
||||||
QUOTIENT_ASSIGN /=
|
|
||||||
REMAINDER_ASSIGN %=
|
|
||||||
|
|
||||||
AND_ASSIGN &=
|
|
||||||
OR_ASSIGN |=
|
|
||||||
EXCLUSIVE_OR_ASSIGN ^=
|
|
||||||
SHIFT_LEFT_ASSIGN <<=
|
|
||||||
SHIFT_RIGHT_ASSIGN >>=
|
|
||||||
UNSIGNED_SHIFT_RIGHT_ASSIGN >>>=
|
|
||||||
AND_NOT_ASSIGN &^=
|
|
||||||
|
|
||||||
LOGICAL_AND &&
|
|
||||||
LOGICAL_OR ||
|
|
||||||
INCREMENT ++
|
|
||||||
DECREMENT --
|
|
||||||
|
|
||||||
EQUAL ==
|
|
||||||
STRICT_EQUAL ===
|
|
||||||
LESS <
|
|
||||||
GREATER >
|
|
||||||
ASSIGN =
|
|
||||||
NOT !
|
|
||||||
|
|
||||||
BITWISE_NOT ~
|
|
||||||
|
|
||||||
NOT_EQUAL !=
|
|
||||||
STRICT_NOT_EQUAL !==
|
|
||||||
LESS_OR_EQUAL <=
|
|
||||||
GREATER_OR_EQUAL <=
|
|
||||||
|
|
||||||
LEFT_PARENTHESIS (
|
|
||||||
LEFT_BRACKET [
|
|
||||||
LEFT_BRACE {
|
|
||||||
COMMA ,
|
|
||||||
PERIOD .
|
|
||||||
|
|
||||||
RIGHT_PARENTHESIS )
|
|
||||||
RIGHT_BRACKET ]
|
|
||||||
RIGHT_BRACE }
|
|
||||||
SEMICOLON ;
|
|
||||||
COLON :
|
|
||||||
QUESTION_MARK ?
|
|
||||||
|
|
||||||
firstKeyword
|
|
||||||
IF
|
|
||||||
IN
|
|
||||||
DO
|
|
||||||
|
|
||||||
VAR
|
|
||||||
FOR
|
|
||||||
NEW
|
|
||||||
TRY
|
|
||||||
|
|
||||||
THIS
|
|
||||||
ELSE
|
|
||||||
CASE
|
|
||||||
VOID
|
|
||||||
WITH
|
|
||||||
|
|
||||||
WHILE
|
|
||||||
BREAK
|
|
||||||
CATCH
|
|
||||||
THROW
|
|
||||||
|
|
||||||
RETURN
|
|
||||||
TYPEOF
|
|
||||||
DELETE
|
|
||||||
SWITCH
|
|
||||||
|
|
||||||
DEFAULT
|
|
||||||
FINALLY
|
|
||||||
|
|
||||||
FUNCTION
|
|
||||||
CONTINUE
|
|
||||||
DEBUGGER
|
|
||||||
|
|
||||||
INSTANCEOF
|
|
||||||
lastKeyword
|
|
||||||
_END_
|
|
||||||
chomp;
|
|
||||||
|
|
||||||
next if m/^\s*#/;
|
|
||||||
|
|
||||||
my ($name, $symbol) = m/(\w+)\s*(\S+)?/;
|
|
||||||
|
|
||||||
if (defined $symbol) {
|
|
||||||
push @order, $name;
|
|
||||||
push @const, "$name // $symbol";
|
|
||||||
$token{$name} = $symbol;
|
|
||||||
} elsif (defined $name) {
|
|
||||||
$keywords ||= $name eq 'firstKeyword';
|
|
||||||
|
|
||||||
push @const, $name;
|
|
||||||
#$const[-1] .= " Token = iota" if 2 == @const;
|
|
||||||
if ($name =~ m/^([A-Z]+)/) {
|
|
||||||
push @keywords, $name if $keywords;
|
|
||||||
push @order, $name;
|
|
||||||
if ($token{SEMICOLON}) {
|
|
||||||
$token{$name} = lc $1;
|
|
||||||
} else {
|
|
||||||
$token{$name} = $name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
push @const, "";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
push @const, ")";
|
|
||||||
print join "\n", @const, "";
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
print <<_END_;
|
|
||||||
|
|
||||||
var token2string = [...]string{
|
|
||||||
_END_
|
|
||||||
for my $name (@order) {
|
|
||||||
print "$name: \"$token{$name}\",\n";
|
|
||||||
}
|
|
||||||
print <<_END_;
|
|
||||||
}
|
|
||||||
_END_
|
|
||||||
|
|
||||||
print <<_END_;
|
|
||||||
|
|
||||||
var keywordTable = map[string]_keyword{
|
|
||||||
_END_
|
|
||||||
for my $name (@keywords) {
|
|
||||||
print <<_END_
|
|
||||||
"@{[ lc $name ]}": _keyword{
|
|
||||||
token: $name,
|
|
||||||
},
|
|
||||||
_END_
|
|
||||||
}
|
|
||||||
|
|
||||||
for my $name (qw/
|
|
||||||
const
|
|
||||||
class
|
|
||||||
enum
|
|
||||||
export
|
|
||||||
extends
|
|
||||||
import
|
|
||||||
super
|
|
||||||
/) {
|
|
||||||
print <<_END_
|
|
||||||
"$name": _keyword{
|
|
||||||
token: KEYWORD,
|
|
||||||
futureKeyword: true,
|
|
||||||
},
|
|
||||||
_END_
|
|
||||||
}
|
|
||||||
|
|
||||||
for my $name (qw/
|
|
||||||
implements
|
|
||||||
interface
|
|
||||||
let
|
|
||||||
package
|
|
||||||
private
|
|
||||||
protected
|
|
||||||
public
|
|
||||||
static
|
|
||||||
/) {
|
|
||||||
print <<_END_
|
|
||||||
"$name": _keyword{
|
|
||||||
token: KEYWORD,
|
|
||||||
futureKeyword: true,
|
|
||||||
strict: true,
|
|
||||||
},
|
|
||||||
_END_
|
|
||||||
}
|
|
||||||
|
|
||||||
print <<_END_;
|
|
||||||
}
|
|
||||||
_END_
|
|
||||||
}
|
|
86
v1/vendor/github.com/robertkrimen/otto/type_arguments.go
generated
vendored
|
@ -4,103 +4,103 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (runtime *_runtime) newArgumentsObject(indexOfParameterName []string, stash _stash, length int) *_object {
|
func (rt *runtime) newArgumentsObject(indexOfParameterName []string, stash stasher, length int) *object {
|
||||||
self := runtime.newClassObject("Arguments")
|
obj := rt.newClassObject("Arguments")
|
||||||
|
|
||||||
for index, _ := range indexOfParameterName {
|
for index := range indexOfParameterName {
|
||||||
name := strconv.FormatInt(int64(index), 10)
|
name := strconv.FormatInt(int64(index), 10)
|
||||||
objectDefineOwnProperty(self, name, _property{Value{}, 0111}, false)
|
objectDefineOwnProperty(obj, name, property{Value{}, 0o111}, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
self.objectClass = _classArguments
|
obj.objectClass = classArguments
|
||||||
self.value = _argumentsObject{
|
obj.value = argumentsObject{
|
||||||
indexOfParameterName: indexOfParameterName,
|
indexOfParameterName: indexOfParameterName,
|
||||||
stash: stash,
|
stash: stash,
|
||||||
}
|
}
|
||||||
|
|
||||||
self.prototype = runtime.global.ObjectPrototype
|
obj.prototype = rt.global.ObjectPrototype
|
||||||
|
|
||||||
self.defineProperty(propertyLength, toValue_int(length), 0101, false)
|
obj.defineProperty(propertyLength, intValue(length), 0o101, false)
|
||||||
|
|
||||||
return self
|
return obj
|
||||||
}
|
}
|
||||||
|
|
||||||
type _argumentsObject struct {
|
type argumentsObject struct {
|
||||||
indexOfParameterName []string
|
indexOfParameterName []string
|
||||||
// function(abc, def, ghi)
|
// function(abc, def, ghi)
|
||||||
// indexOfParameterName[0] = "abc"
|
// indexOfParameterName[0] = "abc"
|
||||||
// indexOfParameterName[1] = "def"
|
// indexOfParameterName[1] = "def"
|
||||||
// indexOfParameterName[2] = "ghi"
|
// indexOfParameterName[2] = "ghi"
|
||||||
// ...
|
// ...
|
||||||
stash _stash
|
stash stasher
|
||||||
}
|
}
|
||||||
|
|
||||||
func (in _argumentsObject) clone(clone *_clone) _argumentsObject {
|
func (o argumentsObject) clone(c *cloner) argumentsObject {
|
||||||
indexOfParameterName := make([]string, len(in.indexOfParameterName))
|
indexOfParameterName := make([]string, len(o.indexOfParameterName))
|
||||||
copy(indexOfParameterName, in.indexOfParameterName)
|
copy(indexOfParameterName, o.indexOfParameterName)
|
||||||
return _argumentsObject{
|
return argumentsObject{
|
||||||
indexOfParameterName,
|
indexOfParameterName,
|
||||||
clone.stash(in.stash),
|
c.stash(o.stash),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self _argumentsObject) get(name string) (Value, bool) {
|
func (o argumentsObject) get(name string) (Value, bool) {
|
||||||
index := stringToArrayIndex(name)
|
index := stringToArrayIndex(name)
|
||||||
if index >= 0 && index < int64(len(self.indexOfParameterName)) {
|
if index >= 0 && index < int64(len(o.indexOfParameterName)) {
|
||||||
name := self.indexOfParameterName[index]
|
name := o.indexOfParameterName[index]
|
||||||
if name == "" {
|
if name == "" {
|
||||||
return Value{}, false
|
return Value{}, false
|
||||||
}
|
}
|
||||||
return self.stash.getBinding(name, false), true
|
return o.stash.getBinding(name, false), true
|
||||||
}
|
}
|
||||||
return Value{}, false
|
return Value{}, false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self _argumentsObject) put(name string, value Value) {
|
func (o argumentsObject) put(name string, value Value) {
|
||||||
index := stringToArrayIndex(name)
|
index := stringToArrayIndex(name)
|
||||||
name = self.indexOfParameterName[index]
|
name = o.indexOfParameterName[index]
|
||||||
self.stash.setBinding(name, value, false)
|
o.stash.setBinding(name, value, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self _argumentsObject) delete(name string) {
|
func (o argumentsObject) delete(name string) {
|
||||||
index := stringToArrayIndex(name)
|
index := stringToArrayIndex(name)
|
||||||
self.indexOfParameterName[index] = ""
|
o.indexOfParameterName[index] = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func argumentsGet(self *_object, name string) Value {
|
func argumentsGet(obj *object, name string) Value {
|
||||||
if value, exists := self.value.(_argumentsObject).get(name); exists {
|
if value, exists := obj.value.(argumentsObject).get(name); exists {
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
return objectGet(self, name)
|
return objectGet(obj, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func argumentsGetOwnProperty(self *_object, name string) *_property {
|
func argumentsGetOwnProperty(obj *object, name string) *property {
|
||||||
property := objectGetOwnProperty(self, name)
|
prop := objectGetOwnProperty(obj, name)
|
||||||
if value, exists := self.value.(_argumentsObject).get(name); exists {
|
if value, exists := obj.value.(argumentsObject).get(name); exists {
|
||||||
property.value = value
|
prop.value = value
|
||||||
}
|
}
|
||||||
return property
|
return prop
|
||||||
}
|
}
|
||||||
|
|
||||||
func argumentsDefineOwnProperty(self *_object, name string, descriptor _property, throw bool) bool {
|
func argumentsDefineOwnProperty(obj *object, name string, descriptor property, throw bool) bool {
|
||||||
if _, exists := self.value.(_argumentsObject).get(name); exists {
|
if _, exists := obj.value.(argumentsObject).get(name); exists {
|
||||||
if !objectDefineOwnProperty(self, name, descriptor, false) {
|
if !objectDefineOwnProperty(obj, name, descriptor, false) {
|
||||||
return self.runtime.typeErrorResult(throw)
|
return obj.runtime.typeErrorResult(throw)
|
||||||
}
|
}
|
||||||
if value, valid := descriptor.value.(Value); valid {
|
if value, valid := descriptor.value.(Value); valid {
|
||||||
self.value.(_argumentsObject).put(name, value)
|
obj.value.(argumentsObject).put(name, value)
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return objectDefineOwnProperty(self, name, descriptor, throw)
|
return objectDefineOwnProperty(obj, name, descriptor, throw)
|
||||||
}
|
}
|
||||||
|
|
||||||
func argumentsDelete(self *_object, name string, throw bool) bool {
|
func argumentsDelete(obj *object, name string, throw bool) bool {
|
||||||
if !objectDelete(self, name, throw) {
|
if !objectDelete(obj, name, throw) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if _, exists := self.value.(_argumentsObject).get(name); exists {
|
if _, exists := obj.value.(argumentsObject).get(name); exists {
|
||||||
self.value.(_argumentsObject).delete(name)
|
obj.value.(argumentsObject).delete(name)
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
100
v1/vendor/github.com/robertkrimen/otto/type_array.go
generated
vendored
|
@ -4,43 +4,43 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (runtime *_runtime) newArrayObject(length uint32) *_object {
|
func (rt *runtime) newArrayObject(length uint32) *object {
|
||||||
self := runtime.newObject()
|
obj := rt.newObject()
|
||||||
self.class = classArray
|
obj.class = classArrayName
|
||||||
self.defineProperty(propertyLength, toValue_uint32(length), 0100, false)
|
obj.defineProperty(propertyLength, uint32Value(length), 0o100, false)
|
||||||
self.objectClass = _classArray
|
obj.objectClass = classArray
|
||||||
return self
|
return obj
|
||||||
}
|
}
|
||||||
|
|
||||||
func isArray(object *_object) bool {
|
func isArray(obj *object) bool {
|
||||||
if object == nil {
|
if obj == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
switch object.class {
|
switch obj.class {
|
||||||
case classArray, classGoArray, classGoSlice:
|
case classArrayName, classGoArrayName, classGoSliceName:
|
||||||
return true
|
return true
|
||||||
default:
|
default:
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func objectLength(object *_object) uint32 {
|
func objectLength(obj *object) uint32 {
|
||||||
if object == nil {
|
if obj == nil {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
switch object.class {
|
switch obj.class {
|
||||||
case classArray:
|
case classArrayName:
|
||||||
return object.get(propertyLength).value.(uint32)
|
return obj.get(propertyLength).value.(uint32)
|
||||||
case classString:
|
case classStringName:
|
||||||
return uint32(object.get(propertyLength).value.(int))
|
return uint32(obj.get(propertyLength).value.(int))
|
||||||
case classGoArray, classGoSlice:
|
case classGoArrayName, classGoSliceName:
|
||||||
return uint32(object.get(propertyLength).value.(int))
|
return uint32(obj.get(propertyLength).value.(int))
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func arrayUint32(rt *_runtime, value Value) uint32 {
|
func arrayUint32(rt *runtime, value Value) uint32 {
|
||||||
nm := value.number()
|
nm := value.number()
|
||||||
if nm.kind != numberInteger || !isUint32(nm.int64) {
|
if nm.kind != numberInteger || !isUint32(nm.int64) {
|
||||||
// FIXME
|
// FIXME
|
||||||
|
@ -49,70 +49,72 @@ func arrayUint32(rt *_runtime, value Value) uint32 {
|
||||||
return uint32(nm.int64)
|
return uint32(nm.int64)
|
||||||
}
|
}
|
||||||
|
|
||||||
func arrayDefineOwnProperty(self *_object, name string, descriptor _property, throw bool) bool {
|
func arrayDefineOwnProperty(obj *object, name string, descriptor property, throw bool) bool {
|
||||||
lengthProperty := self.getOwnProperty(propertyLength)
|
lengthProperty := obj.getOwnProperty(propertyLength)
|
||||||
lengthValue, valid := lengthProperty.value.(Value)
|
lengthValue, valid := lengthProperty.value.(Value)
|
||||||
if !valid {
|
if !valid {
|
||||||
panic("Array.length != Value{}")
|
panic("Array.length != Value{}")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reject := func(reason string) bool {
|
||||||
|
if throw {
|
||||||
|
panic(obj.runtime.panicTypeError("Array.DefineOwnProperty %s", reason))
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
length := lengthValue.value.(uint32)
|
length := lengthValue.value.(uint32)
|
||||||
if name == propertyLength {
|
if name == propertyLength {
|
||||||
if descriptor.value == nil {
|
if descriptor.value == nil {
|
||||||
return objectDefineOwnProperty(self, name, descriptor, throw)
|
return objectDefineOwnProperty(obj, name, descriptor, throw)
|
||||||
}
|
}
|
||||||
newLengthValue, isValue := descriptor.value.(Value)
|
newLengthValue, isValue := descriptor.value.(Value)
|
||||||
if !isValue {
|
if !isValue {
|
||||||
panic(self.runtime.panicTypeError())
|
panic(obj.runtime.panicTypeError("Array.DefineOwnProperty %q is not a value", descriptor.value))
|
||||||
}
|
}
|
||||||
newLength := arrayUint32(self.runtime, newLengthValue)
|
newLength := arrayUint32(obj.runtime, newLengthValue)
|
||||||
descriptor.value = toValue_uint32(newLength)
|
descriptor.value = uint32Value(newLength)
|
||||||
if newLength > length {
|
if newLength > length {
|
||||||
return objectDefineOwnProperty(self, name, descriptor, throw)
|
return objectDefineOwnProperty(obj, name, descriptor, throw)
|
||||||
}
|
}
|
||||||
if !lengthProperty.writable() {
|
if !lengthProperty.writable() {
|
||||||
goto Reject
|
return reject("property length for not writable")
|
||||||
}
|
}
|
||||||
newWritable := true
|
newWritable := true
|
||||||
if descriptor.mode&0700 == 0 {
|
if descriptor.mode&0o700 == 0 {
|
||||||
// If writable is off
|
// If writable is off
|
||||||
newWritable = false
|
newWritable = false
|
||||||
descriptor.mode |= 0100
|
descriptor.mode |= 0o100
|
||||||
}
|
}
|
||||||
if !objectDefineOwnProperty(self, name, descriptor, throw) {
|
if !objectDefineOwnProperty(obj, name, descriptor, throw) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
for newLength < length {
|
for newLength < length {
|
||||||
length--
|
length--
|
||||||
if !self.delete(strconv.FormatInt(int64(length), 10), false) {
|
if !obj.delete(strconv.FormatInt(int64(length), 10), false) {
|
||||||
descriptor.value = toValue_uint32(length + 1)
|
descriptor.value = uint32Value(length + 1)
|
||||||
if !newWritable {
|
if !newWritable {
|
||||||
descriptor.mode &= 0077
|
descriptor.mode &= 0o077
|
||||||
}
|
}
|
||||||
objectDefineOwnProperty(self, name, descriptor, false)
|
objectDefineOwnProperty(obj, name, descriptor, false)
|
||||||
goto Reject
|
return reject("delete failed")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !newWritable {
|
if !newWritable {
|
||||||
descriptor.mode &= 0077
|
descriptor.mode &= 0o077
|
||||||
objectDefineOwnProperty(self, name, descriptor, false)
|
objectDefineOwnProperty(obj, name, descriptor, false)
|
||||||
}
|
}
|
||||||
} else if index := stringToArrayIndex(name); index >= 0 {
|
} else if index := stringToArrayIndex(name); index >= 0 {
|
||||||
if index >= int64(length) && !lengthProperty.writable() {
|
if index >= int64(length) && !lengthProperty.writable() {
|
||||||
goto Reject
|
return reject("property length not writable")
|
||||||
}
|
}
|
||||||
if !objectDefineOwnProperty(self, strconv.FormatInt(index, 10), descriptor, false) {
|
if !objectDefineOwnProperty(obj, strconv.FormatInt(index, 10), descriptor, false) {
|
||||||
goto Reject
|
return reject("Object.DefineOwnProperty failed")
|
||||||
}
|
}
|
||||||
if index >= int64(length) {
|
if index >= int64(length) {
|
||||||
lengthProperty.value = toValue_uint32(uint32(index + 1))
|
lengthProperty.value = uint32Value(uint32(index + 1))
|
||||||
objectDefineOwnProperty(self, propertyLength, *lengthProperty, false)
|
objectDefineOwnProperty(obj, propertyLength, *lengthProperty, false)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return objectDefineOwnProperty(self, name, descriptor, throw)
|
return objectDefineOwnProperty(obj, name, descriptor, throw)
|
||||||
Reject:
|
|
||||||
if throw {
|
|
||||||
panic(self.runtime.panicTypeError())
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
4
v1/vendor/github.com/robertkrimen/otto/type_boolean.go
generated
vendored
|
@ -1,5 +1,5 @@
|
||||||
package otto
|
package otto
|
||||||
|
|
||||||
func (runtime *_runtime) newBooleanObject(value Value) *_object {
|
func (rt *runtime) newBooleanObject(value Value) *object {
|
||||||
return runtime.newPrimitiveObject(classBoolean, toValue_bool(value.bool()))
|
return rt.newPrimitiveObject(classBooleanName, boolValue(value.bool()))
|
||||||
}
|
}
|
||||||
|
|
162
v1/vendor/github.com/robertkrimen/otto/type_date.go
generated
vendored
|
@ -7,23 +7,21 @@ import (
|
||||||
Time "time"
|
Time "time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type _dateObject struct {
|
type dateObject struct {
|
||||||
time Time.Time // Time from the "time" package, a cached version of time
|
time Time.Time // Time from the "time" package, a cached version of time
|
||||||
epoch int64
|
epoch int64
|
||||||
value Value
|
value Value
|
||||||
isNaN bool
|
isNaN bool
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var invalidDateObject = dateObject{
|
||||||
invalidDateObject = _dateObject{
|
|
||||||
time: Time.Time{},
|
time: Time.Time{},
|
||||||
epoch: -1,
|
epoch: -1,
|
||||||
value: NaNValue(),
|
value: NaNValue(),
|
||||||
isNaN: true,
|
isNaN: true,
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
type _ecmaTime struct {
|
type ecmaTime struct {
|
||||||
year int
|
year int
|
||||||
month int
|
month int
|
||||||
day int
|
day int
|
||||||
|
@ -34,8 +32,8 @@ type _ecmaTime struct {
|
||||||
location *Time.Location // Basically, either local or UTC
|
location *Time.Location // Basically, either local or UTC
|
||||||
}
|
}
|
||||||
|
|
||||||
func ecmaTime(goTime Time.Time) _ecmaTime {
|
func newEcmaTime(goTime Time.Time) ecmaTime {
|
||||||
return _ecmaTime{
|
return ecmaTime{
|
||||||
goTime.Year(),
|
goTime.Year(),
|
||||||
dateFromGoMonth(goTime.Month()),
|
dateFromGoMonth(goTime.Month()),
|
||||||
goTime.Day(),
|
goTime.Day(),
|
||||||
|
@ -47,58 +45,58 @@ func ecmaTime(goTime Time.Time) _ecmaTime {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_ecmaTime) goTime() Time.Time {
|
func (t *ecmaTime) goTime() Time.Time {
|
||||||
return Time.Date(
|
return Time.Date(
|
||||||
self.year,
|
t.year,
|
||||||
dateToGoMonth(self.month),
|
dateToGoMonth(t.month),
|
||||||
self.day,
|
t.day,
|
||||||
self.hour,
|
t.hour,
|
||||||
self.minute,
|
t.minute,
|
||||||
self.second,
|
t.second,
|
||||||
self.millisecond*(100*100*100),
|
t.millisecond*(100*100*100),
|
||||||
self.location,
|
t.location,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_dateObject) Time() Time.Time {
|
func (d *dateObject) Time() Time.Time {
|
||||||
return self.time
|
return d.time
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_dateObject) Epoch() int64 {
|
func (d *dateObject) Epoch() int64 {
|
||||||
return self.epoch
|
return d.epoch
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_dateObject) Value() Value {
|
func (d *dateObject) Value() Value {
|
||||||
return self.value
|
return d.value
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME A date should only be in the range of -100,000,000 to +100,000,000 (1970): 15.9.1.1
|
// FIXME A date should only be in the range of -100,000,000 to +100,000,000 (1970): 15.9.1.1.
|
||||||
func (self *_dateObject) SetNaN() {
|
func (d *dateObject) SetNaN() {
|
||||||
self.time = Time.Time{}
|
d.time = Time.Time{}
|
||||||
self.epoch = -1
|
d.epoch = -1
|
||||||
self.value = NaNValue()
|
d.value = NaNValue()
|
||||||
self.isNaN = true
|
d.isNaN = true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_dateObject) SetTime(time Time.Time) {
|
func (d *dateObject) SetTime(time Time.Time) {
|
||||||
self.Set(timeToEpoch(time))
|
d.Set(timeToEpoch(time))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_dateObject) Set(epoch float64) {
|
func (d *dateObject) Set(epoch float64) {
|
||||||
// epoch
|
// epoch
|
||||||
self.epoch = epochToInteger(epoch)
|
d.epoch = epochToInteger(epoch)
|
||||||
|
|
||||||
// time
|
// time
|
||||||
time, err := epochToTime(epoch)
|
time, err := epochToTime(epoch)
|
||||||
self.time = time // Is either a valid time, or the zero-value for time.Time
|
d.time = time // Is either a valid time, or the zero-value for time.Time
|
||||||
|
|
||||||
// value & isNaN
|
// value & isNaN
|
||||||
if err != nil {
|
if err != nil {
|
||||||
self.isNaN = true
|
d.isNaN = true
|
||||||
self.epoch = -1
|
d.epoch = -1
|
||||||
self.value = NaNValue()
|
d.value = NaNValue()
|
||||||
} else {
|
} else {
|
||||||
self.value = toValue_int64(self.epoch)
|
d.value = int64Value(d.epoch)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,48 +107,49 @@ func epochToInteger(value float64) int64 {
|
||||||
return int64(math.Ceil(value))
|
return int64(math.Ceil(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
func epochToTime(value float64) (time Time.Time, err error) {
|
func epochToTime(value float64) (Time.Time, error) {
|
||||||
epochWithMilli := value
|
epochWithMilli := value
|
||||||
if math.IsNaN(epochWithMilli) || math.IsInf(epochWithMilli, 0) {
|
if math.IsNaN(epochWithMilli) || math.IsInf(epochWithMilli, 0) {
|
||||||
err = fmt.Errorf("Invalid time %v", value)
|
return Time.Time{}, fmt.Errorf("invalid time %v", value)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
epoch := int64(epochWithMilli / 1000)
|
epoch := int64(epochWithMilli / 1000)
|
||||||
milli := int64(epochWithMilli) % 1000
|
milli := int64(epochWithMilli) % 1000
|
||||||
|
|
||||||
time = Time.Unix(int64(epoch), milli*1000000).In(utcTimeZone)
|
return Time.Unix(epoch, milli*1000000).In(utcTimeZone), nil
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func timeToEpoch(time Time.Time) float64 {
|
func timeToEpoch(time Time.Time) float64 {
|
||||||
return float64(time.UnixMilli())
|
return float64(time.UnixMilli())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (runtime *_runtime) newDateObject(epoch float64) *_object {
|
func (rt *runtime) newDateObject(epoch float64) *object {
|
||||||
self := runtime.newObject()
|
obj := rt.newObject()
|
||||||
self.class = classDate
|
obj.class = classDateName
|
||||||
|
|
||||||
// FIXME This is ugly...
|
// FIXME This is ugly...
|
||||||
date := _dateObject{}
|
date := dateObject{}
|
||||||
date.Set(epoch)
|
date.Set(epoch)
|
||||||
self.value = date
|
obj.value = date
|
||||||
return self
|
return obj
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_object) dateValue() _dateObject {
|
func (o *object) dateValue() dateObject {
|
||||||
value, _ := self.value.(_dateObject)
|
value, _ := o.value.(dateObject)
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
|
|
||||||
func dateObjectOf(rt *_runtime, _dateObject *_object) _dateObject {
|
func dateObjectOf(rt *runtime, date *object) dateObject {
|
||||||
if _dateObject == nil || _dateObject.class != classDate {
|
if date == nil {
|
||||||
panic(rt.panicTypeError())
|
panic(rt.panicTypeError("Date.ObjectOf is nil"))
|
||||||
}
|
}
|
||||||
return _dateObject.dateValue()
|
if date.class != classDateName {
|
||||||
|
panic(rt.panicTypeError("Date.ObjectOf %q != %q", date.class, classDateName))
|
||||||
|
}
|
||||||
|
return date.dateValue()
|
||||||
}
|
}
|
||||||
|
|
||||||
// JavaScript is 0-based, Go is 1-based (15.9.1.4)
|
// JavaScript is 0-based, Go is 1-based (15.9.1.4).
|
||||||
func dateToGoMonth(month int) Time.Month {
|
func dateToGoMonth(month int) Time.Month {
|
||||||
return Time.Month(month + 1)
|
return Time.Month(month + 1)
|
||||||
}
|
}
|
||||||
|
@ -163,7 +162,8 @@ func dateFromGoDay(day Time.Weekday) int {
|
||||||
return int(day)
|
return int(day)
|
||||||
}
|
}
|
||||||
|
|
||||||
func newDateTime(argumentList []Value, location *Time.Location) (epoch float64) {
|
// newDateTime returns the epoch of date contained in argumentList for location.
|
||||||
|
func newDateTime(argumentList []Value, location *Time.Location) float64 {
|
||||||
pick := func(index int, default_ float64) (float64, bool) {
|
pick := func(index int, default_ float64) (float64, bool) {
|
||||||
if index >= len(argumentList) {
|
if index >= len(argumentList) {
|
||||||
return default_, false
|
return default_, false
|
||||||
|
@ -175,29 +175,41 @@ func newDateTime(argumentList []Value, location *Time.Location) (epoch float64)
|
||||||
return value, false
|
return value, false
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(argumentList) >= 2 { // 2-argument, 3-argument, ...
|
switch len(argumentList) {
|
||||||
|
case 0: // 0-argument
|
||||||
|
time := Time.Now().In(utcTimeZone)
|
||||||
|
return timeToEpoch(time)
|
||||||
|
case 1: // 1-argument
|
||||||
|
value := valueOfArrayIndex(argumentList, 0)
|
||||||
|
value = toPrimitiveValue(value)
|
||||||
|
if value.IsString() {
|
||||||
|
return dateParse(value.string())
|
||||||
|
}
|
||||||
|
|
||||||
|
return value.float64()
|
||||||
|
default: // 2-argument, 3-argument, ...
|
||||||
var year, month, day, hour, minute, second, millisecond float64
|
var year, month, day, hour, minute, second, millisecond float64
|
||||||
var invalid bool
|
var invalid bool
|
||||||
if year, invalid = pick(0, 1900.0); invalid {
|
if year, invalid = pick(0, 1900.0); invalid {
|
||||||
goto INVALID
|
return math.NaN()
|
||||||
}
|
}
|
||||||
if month, invalid = pick(1, 0.0); invalid {
|
if month, invalid = pick(1, 0.0); invalid {
|
||||||
goto INVALID
|
return math.NaN()
|
||||||
}
|
}
|
||||||
if day, invalid = pick(2, 1.0); invalid {
|
if day, invalid = pick(2, 1.0); invalid {
|
||||||
goto INVALID
|
return math.NaN()
|
||||||
}
|
}
|
||||||
if hour, invalid = pick(3, 0.0); invalid {
|
if hour, invalid = pick(3, 0.0); invalid {
|
||||||
goto INVALID
|
return math.NaN()
|
||||||
}
|
}
|
||||||
if minute, invalid = pick(4, 0.0); invalid {
|
if minute, invalid = pick(4, 0.0); invalid {
|
||||||
goto INVALID
|
return math.NaN()
|
||||||
}
|
}
|
||||||
if second, invalid = pick(5, 0.0); invalid {
|
if second, invalid = pick(5, 0.0); invalid {
|
||||||
goto INVALID
|
return math.NaN()
|
||||||
}
|
}
|
||||||
if millisecond, invalid = pick(6, 0.0); invalid {
|
if millisecond, invalid = pick(6, 0.0); invalid {
|
||||||
goto INVALID
|
return math.NaN()
|
||||||
}
|
}
|
||||||
|
|
||||||
if year >= 0 && year <= 99 {
|
if year >= 0 && year <= 99 {
|
||||||
|
@ -206,22 +218,7 @@ func newDateTime(argumentList []Value, location *Time.Location) (epoch float64)
|
||||||
|
|
||||||
time := Time.Date(int(year), dateToGoMonth(int(month)), int(day), int(hour), int(minute), int(second), int(millisecond)*1000*1000, location)
|
time := Time.Date(int(year), dateToGoMonth(int(month)), int(day), int(hour), int(minute), int(second), int(millisecond)*1000*1000, location)
|
||||||
return timeToEpoch(time)
|
return timeToEpoch(time)
|
||||||
} else if len(argumentList) == 0 { // 0-argument
|
|
||||||
time := Time.Now().In(utcTimeZone)
|
|
||||||
return timeToEpoch(time)
|
|
||||||
} else { // 1-argument
|
|
||||||
value := valueOfArrayIndex(argumentList, 0)
|
|
||||||
value = toPrimitive(value)
|
|
||||||
if value.IsString() {
|
|
||||||
return dateParse(value.string())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return value.float64()
|
|
||||||
}
|
|
||||||
|
|
||||||
INVALID:
|
|
||||||
epoch = math.NaN()
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -238,6 +235,10 @@ var (
|
||||||
"2006-01T15:04:05",
|
"2006-01T15:04:05",
|
||||||
"2006-01-02T15:04:05",
|
"2006-01-02T15:04:05",
|
||||||
|
|
||||||
|
"2006/01",
|
||||||
|
"2006/01/02",
|
||||||
|
"2006/01/02 15:04:05",
|
||||||
|
|
||||||
"2006T15:04:05.000",
|
"2006T15:04:05.000",
|
||||||
"2006-01T15:04:05.000",
|
"2006-01T15:04:05.000",
|
||||||
"2006-01-02T15:04:05.000",
|
"2006-01-02T15:04:05.000",
|
||||||
|
@ -259,7 +260,8 @@ var (
|
||||||
matchDateTimeZone = regexp.MustCompile(`^(.*)(?:(Z)|([\+\-]\d{2}):(\d{2}))$`)
|
matchDateTimeZone = regexp.MustCompile(`^(.*)(?:(Z)|([\+\-]\d{2}):(\d{2}))$`)
|
||||||
)
|
)
|
||||||
|
|
||||||
func dateParse(date string) (epoch float64) {
|
// dateParse returns the epoch of the parsed date.
|
||||||
|
func dateParse(date string) float64 {
|
||||||
// YYYY-MM-DDTHH:mm:ss.sssZ
|
// YYYY-MM-DDTHH:mm:ss.sssZ
|
||||||
var time Time.Time
|
var time Time.Time
|
||||||
var err error
|
var err error
|
||||||
|
|
54
v1/vendor/github.com/robertkrimen/otto/type_error.go
generated
vendored
|
@ -1,58 +1,58 @@
|
||||||
package otto
|
package otto
|
||||||
|
|
||||||
func (rt *_runtime) newErrorObject(name string, message Value, stackFramesToPop int) *_object {
|
func (rt *runtime) newErrorObject(name string, message Value, stackFramesToPop int) *object {
|
||||||
self := rt.newClassObject(classError)
|
obj := rt.newClassObject(classErrorName)
|
||||||
if message.IsDefined() {
|
if message.IsDefined() {
|
||||||
msg := message.string()
|
err := newError(rt, name, stackFramesToPop, "%s", message.string())
|
||||||
self.defineProperty("message", toValue_string(msg), 0111, false)
|
obj.defineProperty("message", err.messageValue(), 0o111, false)
|
||||||
self.value = newError(rt, name, stackFramesToPop, msg)
|
obj.value = err
|
||||||
} else {
|
} else {
|
||||||
self.value = newError(rt, name, stackFramesToPop)
|
obj.value = newError(rt, name, stackFramesToPop)
|
||||||
}
|
}
|
||||||
|
|
||||||
self.defineOwnProperty("stack", _property{
|
obj.defineOwnProperty("stack", property{
|
||||||
value: _propertyGetSet{
|
value: propertyGetSet{
|
||||||
rt.newNativeFunction("get", "internal", 0, func(FunctionCall) Value {
|
rt.newNativeFunction("get", "internal", 0, func(FunctionCall) Value {
|
||||||
return toValue_string(self.value.(_error).formatWithStack())
|
return stringValue(obj.value.(ottoError).formatWithStack())
|
||||||
}),
|
}),
|
||||||
&_nilGetSetObject,
|
&nilGetSetObject,
|
||||||
},
|
},
|
||||||
mode: modeConfigureMask & modeOnMask,
|
mode: modeConfigureMask & modeOnMask,
|
||||||
}, false)
|
}, false)
|
||||||
|
|
||||||
return self
|
return obj
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rt *_runtime) newErrorObjectError(err _error) *_object {
|
func (rt *runtime) newErrorObjectError(err ottoError) *object {
|
||||||
self := rt.newClassObject(classError)
|
obj := rt.newClassObject(classErrorName)
|
||||||
self.defineProperty("message", err.messageValue(), 0111, false)
|
obj.defineProperty("message", err.messageValue(), 0o111, false)
|
||||||
self.value = err
|
obj.value = err
|
||||||
switch err.name {
|
switch err.name {
|
||||||
case "EvalError":
|
case "EvalError":
|
||||||
self.prototype = rt.global.EvalErrorPrototype
|
obj.prototype = rt.global.EvalErrorPrototype
|
||||||
case "TypeError":
|
case "TypeError":
|
||||||
self.prototype = rt.global.TypeErrorPrototype
|
obj.prototype = rt.global.TypeErrorPrototype
|
||||||
case "RangeError":
|
case "RangeError":
|
||||||
self.prototype = rt.global.RangeErrorPrototype
|
obj.prototype = rt.global.RangeErrorPrototype
|
||||||
case "ReferenceError":
|
case "ReferenceError":
|
||||||
self.prototype = rt.global.ReferenceErrorPrototype
|
obj.prototype = rt.global.ReferenceErrorPrototype
|
||||||
case "SyntaxError":
|
case "SyntaxError":
|
||||||
self.prototype = rt.global.SyntaxErrorPrototype
|
obj.prototype = rt.global.SyntaxErrorPrototype
|
||||||
case "URIError":
|
case "URIError":
|
||||||
self.prototype = rt.global.URIErrorPrototype
|
obj.prototype = rt.global.URIErrorPrototype
|
||||||
default:
|
default:
|
||||||
self.prototype = rt.global.ErrorPrototype
|
obj.prototype = rt.global.ErrorPrototype
|
||||||
}
|
}
|
||||||
|
|
||||||
self.defineOwnProperty("stack", _property{
|
obj.defineOwnProperty("stack", property{
|
||||||
value: _propertyGetSet{
|
value: propertyGetSet{
|
||||||
rt.newNativeFunction("get", "internal", 0, func(FunctionCall) Value {
|
rt.newNativeFunction("get", "internal", 0, func(FunctionCall) Value {
|
||||||
return toValue_string(self.value.(_error).formatWithStack())
|
return stringValue(obj.value.(ottoError).formatWithStack())
|
||||||
}),
|
}),
|
||||||
&_nilGetSetObject,
|
&nilGetSetObject,
|
||||||
},
|
},
|
||||||
mode: modeConfigureMask & modeOnMask,
|
mode: modeConfigureMask & modeOnMask,
|
||||||
}, false)
|
}, false)
|
||||||
|
|
||||||
return self
|
return obj
|
||||||
}
|
}
|
||||||
|
|
289
v1/vendor/github.com/robertkrimen/otto/type_function.go
generated
vendored
|
@ -1,20 +1,20 @@
|
||||||
package otto
|
package otto
|
||||||
|
|
||||||
// _constructFunction
|
// constructFunction.
|
||||||
type _constructFunction func(*_object, []Value) Value
|
type constructFunction func(*object, []Value) Value
|
||||||
|
|
||||||
// 13.2.2 [[Construct]]
|
// 13.2.2 [[Construct]].
|
||||||
func defaultConstruct(fn *_object, argumentList []Value) Value {
|
func defaultConstruct(fn *object, argumentList []Value) Value {
|
||||||
object := fn.runtime.newObject()
|
obj := fn.runtime.newObject()
|
||||||
object.class = classObject
|
obj.class = classObjectName
|
||||||
|
|
||||||
prototype := fn.get("prototype")
|
prototype := fn.get("prototype")
|
||||||
if prototype.kind != valueObject {
|
if prototype.kind != valueObject {
|
||||||
prototype = toValue_object(fn.runtime.global.ObjectPrototype)
|
prototype = objectValue(fn.runtime.global.ObjectPrototype)
|
||||||
}
|
}
|
||||||
object.prototype = prototype._object()
|
obj.prototype = prototype.object()
|
||||||
|
|
||||||
this := toValue_object(object)
|
this := objectValue(obj)
|
||||||
value := fn.call(this, argumentList, false, nativeFrame)
|
value := fn.call(this, argumentList, false, nativeFrame)
|
||||||
if value.kind == valueObject {
|
if value.kind == valueObject {
|
||||||
return value
|
return value
|
||||||
|
@ -22,72 +22,66 @@ func defaultConstruct(fn *_object, argumentList []Value) Value {
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
// _nativeFunction
|
// nativeFunction.
|
||||||
type _nativeFunction func(FunctionCall) Value
|
type nativeFunction func(FunctionCall) Value
|
||||||
|
|
||||||
// ===================== //
|
// nativeFunctionObject.
|
||||||
// _nativeFunctionObject //
|
type nativeFunctionObject struct {
|
||||||
// ===================== //
|
|
||||||
|
|
||||||
type _nativeFunctionObject struct {
|
|
||||||
name string
|
name string
|
||||||
file string
|
file string
|
||||||
line int
|
line int
|
||||||
call _nativeFunction // [[Call]]
|
call nativeFunction // [[Call]]
|
||||||
construct _constructFunction // [[Construct]]
|
construct constructFunction // [[Construct]]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (runtime *_runtime) _newNativeFunctionObject(name, file string, line int, native _nativeFunction, length int) *_object {
|
func (rt *runtime) newNativeFunctionProperty(name, file string, line int, native nativeFunction, length int) *object {
|
||||||
self := runtime.newClassObject(classFunction)
|
o := rt.newClassObject(classFunctionName)
|
||||||
self.value = _nativeFunctionObject{
|
o.value = nativeFunctionObject{
|
||||||
name: name,
|
name: name,
|
||||||
file: file,
|
file: file,
|
||||||
line: line,
|
line: line,
|
||||||
call: native,
|
call: native,
|
||||||
construct: defaultConstruct,
|
construct: defaultConstruct,
|
||||||
}
|
}
|
||||||
self.defineProperty("name", toValue_string(name), 0000, false)
|
o.defineProperty("name", stringValue(name), 0o000, false)
|
||||||
self.defineProperty(propertyLength, toValue_int(length), 0000, false)
|
o.defineProperty(propertyLength, intValue(length), 0o000, false)
|
||||||
return self
|
return o
|
||||||
}
|
}
|
||||||
|
|
||||||
func (runtime *_runtime) newNativeFunctionObject(name, file string, line int, native _nativeFunction, length int) *_object {
|
func (rt *runtime) newNativeFunctionObject(name, file string, line int, native nativeFunction, length int) *object {
|
||||||
self := runtime._newNativeFunctionObject(name, file, line, native, length)
|
o := rt.newNativeFunctionProperty(name, file, line, native, length)
|
||||||
self.defineOwnProperty("caller", _property{
|
o.defineOwnProperty("caller", property{
|
||||||
value: _propertyGetSet{
|
value: propertyGetSet{
|
||||||
runtime._newNativeFunctionObject("get", "internal", 0, func(fc FunctionCall) Value {
|
rt.newNativeFunctionProperty("get", "internal", 0, func(fc FunctionCall) Value {
|
||||||
for sc := runtime.scope; sc != nil; sc = sc.outer {
|
for sc := rt.scope; sc != nil; sc = sc.outer {
|
||||||
if sc.frame.fn == self {
|
if sc.frame.fn == o {
|
||||||
if sc.outer == nil || sc.outer.frame.fn == nil {
|
if sc.outer == nil || sc.outer.frame.fn == nil {
|
||||||
return nullValue
|
return nullValue
|
||||||
}
|
}
|
||||||
|
|
||||||
return runtime.toValue(sc.outer.frame.fn)
|
return rt.toValue(sc.outer.frame.fn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullValue
|
return nullValue
|
||||||
}, 0),
|
}, 0),
|
||||||
&_nilGetSetObject,
|
&nilGetSetObject,
|
||||||
},
|
},
|
||||||
mode: 0000,
|
mode: 0o000,
|
||||||
}, false)
|
}, false)
|
||||||
return self
|
return o
|
||||||
}
|
}
|
||||||
|
|
||||||
// =================== //
|
// bindFunctionObject.
|
||||||
// _bindFunctionObject //
|
type bindFunctionObject struct {
|
||||||
// =================== //
|
target *object
|
||||||
|
|
||||||
type _bindFunctionObject struct {
|
|
||||||
target *_object
|
|
||||||
this Value
|
this Value
|
||||||
argumentList []Value
|
argumentList []Value
|
||||||
}
|
}
|
||||||
|
|
||||||
func (runtime *_runtime) newBoundFunctionObject(target *_object, this Value, argumentList []Value) *_object {
|
func (rt *runtime) newBoundFunctionObject(target *object, this Value, argumentList []Value) *object {
|
||||||
self := runtime.newClassObject(classFunction)
|
o := rt.newClassObject(classFunctionName)
|
||||||
self.value = _bindFunctionObject{
|
o.value = bindFunctionObject{
|
||||||
target: target,
|
target: target,
|
||||||
this: this,
|
this: this,
|
||||||
argumentList: argumentList,
|
argumentList: argumentList,
|
||||||
|
@ -97,100 +91,96 @@ func (runtime *_runtime) newBoundFunctionObject(target *_object, this Value, arg
|
||||||
if length < 0 {
|
if length < 0 {
|
||||||
length = 0
|
length = 0
|
||||||
}
|
}
|
||||||
self.defineProperty("name", toValue_string("bound "+target.get("name").String()), 0000, false)
|
o.defineProperty("name", stringValue("bound "+target.get("name").String()), 0o000, false)
|
||||||
self.defineProperty(propertyLength, toValue_int(length), 0000, false)
|
o.defineProperty(propertyLength, intValue(length), 0o000, false)
|
||||||
self.defineProperty("caller", Value{}, 0000, false) // TODO Should throw a TypeError
|
o.defineProperty("caller", Value{}, 0o000, false) // TODO Should throw a TypeError
|
||||||
self.defineProperty("arguments", Value{}, 0000, false) // TODO Should throw a TypeError
|
o.defineProperty("arguments", Value{}, 0o000, false) // TODO Should throw a TypeError
|
||||||
return self
|
return o
|
||||||
}
|
}
|
||||||
|
|
||||||
// [[Construct]]
|
// [[Construct]].
|
||||||
func (fn _bindFunctionObject) construct(argumentList []Value) Value {
|
func (fn bindFunctionObject) construct(argumentList []Value) Value {
|
||||||
object := fn.target
|
obj := fn.target
|
||||||
switch value := object.value.(type) {
|
switch value := obj.value.(type) {
|
||||||
case _nativeFunctionObject:
|
case nativeFunctionObject:
|
||||||
return value.construct(object, fn.argumentList)
|
return value.construct(obj, fn.argumentList)
|
||||||
case _nodeFunctionObject:
|
case nodeFunctionObject:
|
||||||
argumentList = append(fn.argumentList, argumentList...)
|
argumentList = append(fn.argumentList, argumentList...)
|
||||||
return object.construct(argumentList)
|
return obj.construct(argumentList)
|
||||||
|
default:
|
||||||
|
panic(fn.target.runtime.panicTypeError("construct unknown type %T", obj.value))
|
||||||
}
|
}
|
||||||
panic(fn.target.runtime.panicTypeError())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// =================== //
|
// nodeFunctionObject.
|
||||||
// _nodeFunctionObject //
|
type nodeFunctionObject struct {
|
||||||
// =================== //
|
node *nodeFunctionLiteral
|
||||||
|
stash stasher
|
||||||
type _nodeFunctionObject struct {
|
|
||||||
node *_nodeFunctionLiteral
|
|
||||||
stash _stash
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (runtime *_runtime) newNodeFunctionObject(node *_nodeFunctionLiteral, stash _stash) *_object {
|
func (rt *runtime) newNodeFunctionObject(node *nodeFunctionLiteral, stash stasher) *object {
|
||||||
self := runtime.newClassObject(classFunction)
|
o := rt.newClassObject(classFunctionName)
|
||||||
self.value = _nodeFunctionObject{
|
o.value = nodeFunctionObject{
|
||||||
node: node,
|
node: node,
|
||||||
stash: stash,
|
stash: stash,
|
||||||
}
|
}
|
||||||
self.defineProperty("name", toValue_string(node.name), 0000, false)
|
o.defineProperty("name", stringValue(node.name), 0o000, false)
|
||||||
self.defineProperty(propertyLength, toValue_int(len(node.parameterList)), 0000, false)
|
o.defineProperty(propertyLength, intValue(len(node.parameterList)), 0o000, false)
|
||||||
self.defineOwnProperty("caller", _property{
|
o.defineOwnProperty("caller", property{
|
||||||
value: _propertyGetSet{
|
value: propertyGetSet{
|
||||||
runtime.newNativeFunction("get", "internal", 0, func(fc FunctionCall) Value {
|
rt.newNativeFunction("get", "internal", 0, func(fc FunctionCall) Value {
|
||||||
for sc := runtime.scope; sc != nil; sc = sc.outer {
|
for sc := rt.scope; sc != nil; sc = sc.outer {
|
||||||
if sc.frame.fn == self {
|
if sc.frame.fn == o {
|
||||||
if sc.outer == nil || sc.outer.frame.fn == nil {
|
if sc.outer == nil || sc.outer.frame.fn == nil {
|
||||||
return nullValue
|
return nullValue
|
||||||
}
|
}
|
||||||
|
|
||||||
return runtime.toValue(sc.outer.frame.fn)
|
return rt.toValue(sc.outer.frame.fn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullValue
|
return nullValue
|
||||||
}),
|
}),
|
||||||
&_nilGetSetObject,
|
&nilGetSetObject,
|
||||||
},
|
},
|
||||||
mode: 0000,
|
mode: 0o000,
|
||||||
}, false)
|
}, false)
|
||||||
return self
|
return o
|
||||||
}
|
}
|
||||||
|
|
||||||
// ======= //
|
// _object.
|
||||||
// _object //
|
func (o *object) isCall() bool {
|
||||||
// ======= //
|
switch fn := o.value.(type) {
|
||||||
|
case nativeFunctionObject:
|
||||||
func (self *_object) isCall() bool {
|
|
||||||
switch fn := self.value.(type) {
|
|
||||||
case _nativeFunctionObject:
|
|
||||||
return fn.call != nil
|
return fn.call != nil
|
||||||
case _bindFunctionObject:
|
case bindFunctionObject:
|
||||||
return true
|
return true
|
||||||
case _nodeFunctionObject:
|
case nodeFunctionObject:
|
||||||
return true
|
return true
|
||||||
}
|
default:
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (self *_object) call(this Value, argumentList []Value, eval bool, frame _frame) Value {
|
func (o *object) call(this Value, argumentList []Value, eval bool, frm frame) Value { //nolint: unparam // Isn't currently used except in recursive self.
|
||||||
switch fn := self.value.(type) {
|
switch fn := o.value.(type) {
|
||||||
case _nativeFunctionObject:
|
case nativeFunctionObject:
|
||||||
// Since eval is a native function, we only have to check for it here
|
// Since eval is a native function, we only have to check for it here
|
||||||
if eval {
|
if eval {
|
||||||
eval = self == self.runtime.eval // If eval is true, then it IS a direct eval
|
eval = o == o.runtime.eval // If eval is true, then it IS a direct eval
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enter a scope, name from the native object...
|
// Enter a scope, name from the native object...
|
||||||
rt := self.runtime
|
rt := o.runtime
|
||||||
if rt.scope != nil && !eval {
|
if rt.scope != nil && !eval {
|
||||||
rt.enterFunctionScope(rt.scope.lexical, this)
|
rt.enterFunctionScope(rt.scope.lexical, this)
|
||||||
rt.scope.frame = _frame{
|
rt.scope.frame = frame{
|
||||||
native: true,
|
native: true,
|
||||||
nativeFile: fn.file,
|
nativeFile: fn.file,
|
||||||
nativeLine: fn.line,
|
nativeLine: fn.line,
|
||||||
callee: fn.name,
|
callee: fn.name,
|
||||||
file: nil,
|
file: nil,
|
||||||
fn: self,
|
fn: o,
|
||||||
}
|
}
|
||||||
defer func() {
|
defer func() {
|
||||||
rt.leaveScope()
|
rt.leaveScope()
|
||||||
|
@ -198,77 +188,77 @@ func (self *_object) call(this Value, argumentList []Value, eval bool, frame _fr
|
||||||
}
|
}
|
||||||
|
|
||||||
return fn.call(FunctionCall{
|
return fn.call(FunctionCall{
|
||||||
runtime: self.runtime,
|
runtime: o.runtime,
|
||||||
eval: eval,
|
eval: eval,
|
||||||
|
|
||||||
This: this,
|
This: this,
|
||||||
ArgumentList: argumentList,
|
ArgumentList: argumentList,
|
||||||
Otto: self.runtime.otto,
|
Otto: o.runtime.otto,
|
||||||
})
|
})
|
||||||
|
|
||||||
case _bindFunctionObject:
|
case bindFunctionObject:
|
||||||
// TODO Passthrough site, do not enter a scope
|
// TODO Passthrough site, do not enter a scope
|
||||||
argumentList = append(fn.argumentList, argumentList...)
|
argumentList = append(fn.argumentList, argumentList...)
|
||||||
return fn.target.call(fn.this, argumentList, false, frame)
|
return fn.target.call(fn.this, argumentList, false, frm)
|
||||||
|
|
||||||
case _nodeFunctionObject:
|
case nodeFunctionObject:
|
||||||
rt := self.runtime
|
rt := o.runtime
|
||||||
stash := rt.enterFunctionScope(fn.stash, this)
|
stash := rt.enterFunctionScope(fn.stash, this)
|
||||||
rt.scope.frame = _frame{
|
rt.scope.frame = frame{
|
||||||
callee: fn.node.name,
|
callee: fn.node.name,
|
||||||
file: fn.node.file,
|
file: fn.node.file,
|
||||||
fn: self,
|
fn: o,
|
||||||
}
|
}
|
||||||
defer func() {
|
defer func() {
|
||||||
rt.leaveScope()
|
rt.leaveScope()
|
||||||
}()
|
}()
|
||||||
callValue := rt.cmpl_call_nodeFunction(self, stash, fn.node, this, argumentList)
|
callValue := rt.cmplCallNodeFunction(o, stash, fn.node, argumentList)
|
||||||
if value, valid := callValue.value.(_result); valid {
|
if value, valid := callValue.value.(result); valid {
|
||||||
return value.value
|
return value.value
|
||||||
}
|
}
|
||||||
return callValue
|
return callValue
|
||||||
}
|
}
|
||||||
|
|
||||||
panic(self.runtime.panicTypeError("%v is not a function", toValue_object(self)))
|
panic(o.runtime.panicTypeError("%v is not a function", objectValue(o)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_object) construct(argumentList []Value) Value {
|
func (o *object) construct(argumentList []Value) Value {
|
||||||
switch fn := self.value.(type) {
|
switch fn := o.value.(type) {
|
||||||
case _nativeFunctionObject:
|
case nativeFunctionObject:
|
||||||
if fn.call == nil {
|
if fn.call == nil {
|
||||||
panic(self.runtime.panicTypeError("%v is not a function", toValue_object(self)))
|
panic(o.runtime.panicTypeError("%v is not a function", objectValue(o)))
|
||||||
}
|
}
|
||||||
if fn.construct == nil {
|
if fn.construct == nil {
|
||||||
panic(self.runtime.panicTypeError("%v is not a constructor", toValue_object(self)))
|
panic(o.runtime.panicTypeError("%v is not a constructor", objectValue(o)))
|
||||||
}
|
}
|
||||||
return fn.construct(self, argumentList)
|
return fn.construct(o, argumentList)
|
||||||
|
|
||||||
case _bindFunctionObject:
|
case bindFunctionObject:
|
||||||
return fn.construct(argumentList)
|
return fn.construct(argumentList)
|
||||||
|
|
||||||
case _nodeFunctionObject:
|
case nodeFunctionObject:
|
||||||
return defaultConstruct(self, argumentList)
|
return defaultConstruct(o, argumentList)
|
||||||
}
|
}
|
||||||
|
|
||||||
panic(self.runtime.panicTypeError("%v is not a function", toValue_object(self)))
|
panic(o.runtime.panicTypeError("%v is not a function", objectValue(o)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// 15.3.5.3
|
// 15.3.5.3.
|
||||||
func (self *_object) hasInstance(of Value) bool {
|
func (o *object) hasInstance(of Value) bool {
|
||||||
if !self.isCall() {
|
if !o.isCall() {
|
||||||
// We should not have a hasInstance method
|
// We should not have a hasInstance method
|
||||||
panic(self.runtime.panicTypeError())
|
panic(o.runtime.panicTypeError("Object.hasInstance not callable"))
|
||||||
}
|
}
|
||||||
if !of.IsObject() {
|
if !of.IsObject() {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
prototype := self.get("prototype")
|
prototype := o.get("prototype")
|
||||||
if !prototype.IsObject() {
|
if !prototype.IsObject() {
|
||||||
panic(self.runtime.panicTypeError())
|
panic(o.runtime.panicTypeError("Object.hasInstance prototype %q is not an object", prototype))
|
||||||
}
|
}
|
||||||
prototypeObject := prototype._object()
|
prototypeObject := prototype.object()
|
||||||
|
|
||||||
value := of._object().prototype
|
value := of.object().prototype
|
||||||
for value != nil {
|
for value != nil {
|
||||||
if value == prototypeObject {
|
if value == prototypeObject {
|
||||||
return true
|
return true
|
||||||
|
@ -278,14 +268,10 @@ func (self *_object) hasInstance(of Value) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============ //
|
|
||||||
// FunctionCall //
|
|
||||||
// ============ //
|
|
||||||
|
|
||||||
// FunctionCall is an encapsulation of a JavaScript function call.
|
// FunctionCall is an encapsulation of a JavaScript function call.
|
||||||
type FunctionCall struct {
|
type FunctionCall struct {
|
||||||
runtime *_runtime
|
runtime *runtime
|
||||||
_thisObject *_object
|
thisObj *object
|
||||||
eval bool // This call is a direct call to eval
|
eval bool // This call is a direct call to eval
|
||||||
|
|
||||||
This Value
|
This Value
|
||||||
|
@ -296,43 +282,42 @@ type FunctionCall struct {
|
||||||
// Argument will return the value of the argument at the given index.
|
// Argument will return the value of the argument at the given index.
|
||||||
//
|
//
|
||||||
// If no such argument exists, undefined is returned.
|
// If no such argument exists, undefined is returned.
|
||||||
func (self FunctionCall) Argument(index int) Value {
|
func (f FunctionCall) Argument(index int) Value {
|
||||||
return valueOfArrayIndex(self.ArgumentList, index)
|
return valueOfArrayIndex(f.ArgumentList, index)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self FunctionCall) getArgument(index int) (Value, bool) {
|
func (f FunctionCall) getArgument(index int) (Value, bool) {
|
||||||
return getValueOfArrayIndex(self.ArgumentList, index)
|
return getValueOfArrayIndex(f.ArgumentList, index)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self FunctionCall) slice(index int) []Value {
|
func (f FunctionCall) slice(index int) []Value {
|
||||||
if index < len(self.ArgumentList) {
|
if index < len(f.ArgumentList) {
|
||||||
return self.ArgumentList[index:]
|
return f.ArgumentList[index:]
|
||||||
}
|
}
|
||||||
return []Value{}
|
return []Value{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *FunctionCall) thisObject() *_object {
|
func (f *FunctionCall) thisObject() *object {
|
||||||
if self._thisObject == nil {
|
if f.thisObj == nil {
|
||||||
this := self.This.resolve() // FIXME Is this right?
|
this := f.This.resolve() // FIXME Is this right?
|
||||||
self._thisObject = self.runtime.toObject(this)
|
f.thisObj = f.runtime.toObject(this)
|
||||||
}
|
}
|
||||||
return self._thisObject
|
return f.thisObj
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *FunctionCall) thisClassObject(class string) *_object {
|
func (f *FunctionCall) thisClassObject(class string) *object {
|
||||||
thisObject := self.thisObject()
|
if o := f.thisObject(); o.class != class {
|
||||||
if thisObject.class != class {
|
panic(f.runtime.panicTypeError("Function.Class %s != %s", o.class, class))
|
||||||
panic(self.runtime.panicTypeError())
|
|
||||||
}
|
}
|
||||||
return self._thisObject
|
return f.thisObj
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self FunctionCall) toObject(value Value) *_object {
|
func (f FunctionCall) toObject(value Value) *object {
|
||||||
return self.runtime.toObject(value)
|
return f.runtime.toObject(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CallerLocation will return file location information (file:line:pos) where this function is being called.
|
// CallerLocation will return file location information (file:line:pos) where this function is being called.
|
||||||
func (self FunctionCall) CallerLocation() string {
|
func (f FunctionCall) CallerLocation() string {
|
||||||
// see error.go for location()
|
// see error.go for location()
|
||||||
return self.runtime.scope.outer.frame.location()
|
return f.runtime.scope.outer.frame.location()
|
||||||
}
|
}
|
||||||
|
|
106
v1/vendor/github.com/robertkrimen/otto/type_go_array.go
generated
vendored
|
@ -5,51 +5,51 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (runtime *_runtime) newGoArrayObject(value reflect.Value) *_object {
|
func (rt *runtime) newGoArrayObject(value reflect.Value) *object {
|
||||||
self := runtime.newObject()
|
o := rt.newObject()
|
||||||
self.class = classGoArray
|
o.class = classGoArrayName
|
||||||
self.objectClass = _classGoArray
|
o.objectClass = classGoArray
|
||||||
self.value = _newGoArrayObject(value)
|
o.value = newGoArrayObject(value)
|
||||||
return self
|
return o
|
||||||
}
|
}
|
||||||
|
|
||||||
type _goArrayObject struct {
|
type goArrayObject struct {
|
||||||
value reflect.Value
|
value reflect.Value
|
||||||
writable bool
|
writable bool
|
||||||
propertyMode _propertyMode
|
propertyMode propertyMode
|
||||||
}
|
}
|
||||||
|
|
||||||
func _newGoArrayObject(value reflect.Value) *_goArrayObject {
|
func newGoArrayObject(value reflect.Value) *goArrayObject {
|
||||||
writable := value.Kind() == reflect.Ptr || value.CanSet() // The Array is addressable (like a Slice)
|
writable := value.Kind() == reflect.Ptr || value.CanSet() // The Array is addressable (like a Slice)
|
||||||
mode := _propertyMode(0010)
|
mode := propertyMode(0o010)
|
||||||
if writable {
|
if writable {
|
||||||
mode = 0110
|
mode = 0o110
|
||||||
}
|
}
|
||||||
self := &_goArrayObject{
|
|
||||||
|
return &goArrayObject{
|
||||||
value: value,
|
value: value,
|
||||||
writable: writable,
|
writable: writable,
|
||||||
propertyMode: mode,
|
propertyMode: mode,
|
||||||
}
|
}
|
||||||
return self
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self _goArrayObject) getValue(name string) (reflect.Value, bool) {
|
func (o goArrayObject) getValue(name string) (reflect.Value, bool) { //nolint: unused
|
||||||
if index, err := strconv.ParseInt(name, 10, 64); err != nil {
|
if index, err := strconv.ParseInt(name, 10, 64); err != nil {
|
||||||
v, ok := self.getValueIndex(index)
|
v, ok := o.getValueIndex(index)
|
||||||
if ok {
|
if ok {
|
||||||
return v, ok
|
return v, ok
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if m := self.value.MethodByName(name); m != (reflect.Value{}) {
|
if m := o.value.MethodByName(name); m != (reflect.Value{}) {
|
||||||
return m, true
|
return m, true
|
||||||
}
|
}
|
||||||
|
|
||||||
return reflect.Value{}, false
|
return reflect.Value{}, false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self _goArrayObject) getValueIndex(index int64) (reflect.Value, bool) {
|
func (o goArrayObject) getValueIndex(index int64) (reflect.Value, bool) {
|
||||||
value := reflect.Indirect(self.value)
|
value := reflect.Indirect(o.value)
|
||||||
if index < int64(value.Len()) {
|
if index < int64(value.Len()) {
|
||||||
return value.Index(int(index)), true
|
return value.Index(int(index)), true
|
||||||
}
|
}
|
||||||
|
@ -57,12 +57,12 @@ func (self _goArrayObject) getValueIndex(index int64) (reflect.Value, bool) {
|
||||||
return reflect.Value{}, false
|
return reflect.Value{}, false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self _goArrayObject) setValue(index int64, value Value) bool {
|
func (o goArrayObject) setValue(index int64, value Value) bool {
|
||||||
indexValue, exists := self.getValueIndex(index)
|
indexValue, exists := o.getValueIndex(index)
|
||||||
if !exists {
|
if !exists {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
reflectValue, err := value.toReflectValue(reflect.Indirect(self.value).Type().Elem())
|
reflectValue, err := value.toReflectValue(reflect.Indirect(o.value).Type().Elem())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@ -70,87 +70,87 @@ func (self _goArrayObject) setValue(index int64, value Value) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func goArrayGetOwnProperty(self *_object, name string) *_property {
|
func goArrayGetOwnProperty(obj *object, name string) *property {
|
||||||
// length
|
// length
|
||||||
if name == propertyLength {
|
if name == propertyLength {
|
||||||
return &_property{
|
return &property{
|
||||||
value: toValue(reflect.Indirect(self.value.(*_goArrayObject).value).Len()),
|
value: toValue(reflect.Indirect(obj.value.(*goArrayObject).value).Len()),
|
||||||
mode: 0,
|
mode: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// .0, .1, .2, ...
|
// .0, .1, .2, ...
|
||||||
if index := stringToArrayIndex(name); index >= 0 {
|
if index := stringToArrayIndex(name); index >= 0 {
|
||||||
object := self.value.(*_goArrayObject)
|
goObj := obj.value.(*goArrayObject)
|
||||||
value := Value{}
|
value := Value{}
|
||||||
reflectValue, exists := object.getValueIndex(index)
|
reflectValue, exists := goObj.getValueIndex(index)
|
||||||
if exists {
|
if exists {
|
||||||
value = self.runtime.toValue(reflectValue.Interface())
|
value = obj.runtime.toValue(reflectValue.Interface())
|
||||||
}
|
}
|
||||||
return &_property{
|
return &property{
|
||||||
value: value,
|
value: value,
|
||||||
mode: object.propertyMode,
|
mode: goObj.propertyMode,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if method := self.value.(*_goArrayObject).value.MethodByName(name); method != (reflect.Value{}) {
|
if method := obj.value.(*goArrayObject).value.MethodByName(name); method != (reflect.Value{}) {
|
||||||
return &_property{
|
return &property{
|
||||||
self.runtime.toValue(method.Interface()),
|
obj.runtime.toValue(method.Interface()),
|
||||||
0110,
|
0o110,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return objectGetOwnProperty(self, name)
|
return objectGetOwnProperty(obj, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func goArrayEnumerate(self *_object, all bool, each func(string) bool) {
|
func goArrayEnumerate(obj *object, all bool, each func(string) bool) {
|
||||||
object := self.value.(*_goArrayObject)
|
goObj := obj.value.(*goArrayObject)
|
||||||
// .0, .1, .2, ...
|
// .0, .1, .2, ...
|
||||||
|
|
||||||
for index, length := 0, object.value.Len(); index < length; index++ {
|
for index, length := 0, goObj.value.Len(); index < length; index++ {
|
||||||
name := strconv.FormatInt(int64(index), 10)
|
name := strconv.FormatInt(int64(index), 10)
|
||||||
if !each(name) {
|
if !each(name) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
objectEnumerate(self, all, each)
|
objectEnumerate(obj, all, each)
|
||||||
}
|
}
|
||||||
|
|
||||||
func goArrayDefineOwnProperty(self *_object, name string, descriptor _property, throw bool) bool {
|
func goArrayDefineOwnProperty(obj *object, name string, descriptor property, throw bool) bool {
|
||||||
if name == propertyLength {
|
if name == propertyLength {
|
||||||
return self.runtime.typeErrorResult(throw)
|
return obj.runtime.typeErrorResult(throw)
|
||||||
} else if index := stringToArrayIndex(name); index >= 0 {
|
} else if index := stringToArrayIndex(name); index >= 0 {
|
||||||
object := self.value.(*_goArrayObject)
|
goObj := obj.value.(*goArrayObject)
|
||||||
if object.writable {
|
if goObj.writable {
|
||||||
if self.value.(*_goArrayObject).setValue(index, descriptor.value.(Value)) {
|
if obj.value.(*goArrayObject).setValue(index, descriptor.value.(Value)) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return self.runtime.typeErrorResult(throw)
|
return obj.runtime.typeErrorResult(throw)
|
||||||
}
|
}
|
||||||
return objectDefineOwnProperty(self, name, descriptor, throw)
|
return objectDefineOwnProperty(obj, name, descriptor, throw)
|
||||||
}
|
}
|
||||||
|
|
||||||
func goArrayDelete(self *_object, name string, throw bool) bool {
|
func goArrayDelete(obj *object, name string, throw bool) bool {
|
||||||
// length
|
// length
|
||||||
if name == propertyLength {
|
if name == propertyLength {
|
||||||
return self.runtime.typeErrorResult(throw)
|
return obj.runtime.typeErrorResult(throw)
|
||||||
}
|
}
|
||||||
|
|
||||||
// .0, .1, .2, ...
|
// .0, .1, .2, ...
|
||||||
index := stringToArrayIndex(name)
|
index := stringToArrayIndex(name)
|
||||||
if index >= 0 {
|
if index >= 0 {
|
||||||
object := self.value.(*_goArrayObject)
|
goObj := obj.value.(*goArrayObject)
|
||||||
if object.writable {
|
if goObj.writable {
|
||||||
indexValue, exists := object.getValueIndex(index)
|
indexValue, exists := goObj.getValueIndex(index)
|
||||||
if exists {
|
if exists {
|
||||||
indexValue.Set(reflect.Zero(reflect.Indirect(object.value).Type().Elem()))
|
indexValue.Set(reflect.Zero(reflect.Indirect(goObj.value).Type().Elem()))
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return self.runtime.typeErrorResult(throw)
|
return obj.runtime.typeErrorResult(throw)
|
||||||
}
|
}
|
||||||
|
|
||||||
return self.delete(name, throw)
|
return obj.delete(name, throw)
|
||||||
}
|
}
|
||||||
|
|
81
v1/vendor/github.com/robertkrimen/otto/type_go_map.go
generated
vendored
|
@ -4,69 +4,82 @@ import (
|
||||||
"reflect"
|
"reflect"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (runtime *_runtime) newGoMapObject(value reflect.Value) *_object {
|
func (rt *runtime) newGoMapObject(value reflect.Value) *object {
|
||||||
self := runtime.newObject()
|
obj := rt.newObject()
|
||||||
self.class = classObject // TODO Should this be something else?
|
obj.class = classObjectName // TODO Should this be something else?
|
||||||
self.objectClass = _classGoMap
|
obj.objectClass = classGoMap
|
||||||
self.value = _newGoMapObject(value)
|
obj.value = newGoMapObject(value)
|
||||||
return self
|
return obj
|
||||||
}
|
}
|
||||||
|
|
||||||
type _goMapObject struct {
|
type goMapObject struct {
|
||||||
value reflect.Value
|
value reflect.Value
|
||||||
keyType reflect.Type
|
keyType reflect.Type
|
||||||
valueType reflect.Type
|
valueType reflect.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
func _newGoMapObject(value reflect.Value) *_goMapObject {
|
func newGoMapObject(value reflect.Value) *goMapObject {
|
||||||
if value.Kind() != reflect.Map {
|
if value.Kind() != reflect.Map {
|
||||||
dbgf("%/panic//%@: %v != reflect.Map", value.Kind())
|
dbgf("%/panic//%@: %v != reflect.Map", value.Kind())
|
||||||
}
|
}
|
||||||
self := &_goMapObject{
|
return &goMapObject{
|
||||||
value: value,
|
value: value,
|
||||||
keyType: value.Type().Key(),
|
keyType: value.Type().Key(),
|
||||||
valueType: value.Type().Elem(),
|
valueType: value.Type().Elem(),
|
||||||
}
|
}
|
||||||
return self
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self _goMapObject) toKey(name string) reflect.Value {
|
func (o goMapObject) toKey(name string) reflect.Value {
|
||||||
reflectValue, err := stringToReflectValue(name, self.keyType.Kind())
|
reflectValue, err := stringToReflectValue(name, o.keyType.Kind())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
return reflectValue
|
return reflectValue
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self _goMapObject) toValue(value Value) reflect.Value {
|
func (o goMapObject) toValue(value Value) reflect.Value {
|
||||||
reflectValue, err := value.toReflectValue(self.valueType)
|
reflectValue, err := value.toReflectValue(o.valueType)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
return reflectValue
|
return reflectValue
|
||||||
}
|
}
|
||||||
|
|
||||||
func goMapGetOwnProperty(self *_object, name string) *_property {
|
func goMapGetOwnProperty(obj *object, name string) *property {
|
||||||
object := self.value.(*_goMapObject)
|
goObj := obj.value.(*goMapObject)
|
||||||
value := object.value.MapIndex(object.toKey(name))
|
|
||||||
|
// an error here means that the key referenced by `name` could not possibly
|
||||||
|
// be a property of this object, so it should be safe to ignore this error
|
||||||
|
//
|
||||||
|
// TODO: figure out if any cases from
|
||||||
|
// https://go.dev/ref/spec#Comparison_operators meet the criteria of 1)
|
||||||
|
// being possible to represent as a string, 2) being possible to reconstruct
|
||||||
|
// from a string, and 3) having a meaningful failure case in this context
|
||||||
|
// other than "key does not exist"
|
||||||
|
key, err := stringToReflectValue(name, goObj.keyType.Kind())
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
value := goObj.value.MapIndex(key)
|
||||||
if value.IsValid() {
|
if value.IsValid() {
|
||||||
return &_property{self.runtime.toValue(value.Interface()), 0111}
|
return &property{obj.runtime.toValue(value.Interface()), 0o111}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Other methods
|
// Other methods
|
||||||
if method := self.value.(*_goMapObject).value.MethodByName(name); method.IsValid() {
|
if method := obj.value.(*goMapObject).value.MethodByName(name); method.IsValid() {
|
||||||
return &_property{
|
return &property{
|
||||||
value: self.runtime.toValue(method.Interface()),
|
value: obj.runtime.toValue(method.Interface()),
|
||||||
mode: 0110,
|
mode: 0o110,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func goMapEnumerate(self *_object, all bool, each func(string) bool) {
|
func goMapEnumerate(obj *object, all bool, each func(string) bool) {
|
||||||
object := self.value.(*_goMapObject)
|
goObj := obj.value.(*goMapObject)
|
||||||
keys := object.value.MapKeys()
|
keys := goObj.value.MapKeys()
|
||||||
for _, key := range keys {
|
for _, key := range keys {
|
||||||
if !each(toValue(key).String()) {
|
if !each(toValue(key).String()) {
|
||||||
return
|
return
|
||||||
|
@ -74,22 +87,22 @@ func goMapEnumerate(self *_object, all bool, each func(string) bool) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func goMapDefineOwnProperty(self *_object, name string, descriptor _property, throw bool) bool {
|
func goMapDefineOwnProperty(obj *object, name string, descriptor property, throw bool) bool {
|
||||||
object := self.value.(*_goMapObject)
|
goObj := obj.value.(*goMapObject)
|
||||||
// TODO ...or 0222
|
// TODO ...or 0222
|
||||||
if descriptor.mode != 0111 {
|
if descriptor.mode != 0o111 {
|
||||||
return self.runtime.typeErrorResult(throw)
|
return obj.runtime.typeErrorResult(throw)
|
||||||
}
|
}
|
||||||
if !descriptor.isDataDescriptor() {
|
if !descriptor.isDataDescriptor() {
|
||||||
return self.runtime.typeErrorResult(throw)
|
return obj.runtime.typeErrorResult(throw)
|
||||||
}
|
}
|
||||||
object.value.SetMapIndex(object.toKey(name), object.toValue(descriptor.value.(Value)))
|
goObj.value.SetMapIndex(goObj.toKey(name), goObj.toValue(descriptor.value.(Value)))
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func goMapDelete(self *_object, name string, throw bool) bool {
|
func goMapDelete(obj *object, name string, throw bool) bool {
|
||||||
object := self.value.(*_goMapObject)
|
goObj := obj.value.(*goMapObject)
|
||||||
object.value.SetMapIndex(object.toKey(name), reflect.Value{})
|
goObj.value.SetMapIndex(goObj.toKey(name), reflect.Value{})
|
||||||
// FIXME
|
// FIXME
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|