Implemented dashboard and login/logout
497
v1/app.go
|
@ -7,17 +7,27 @@ import (
|
|||
"log"
|
||||
"os"
|
||||
"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/models"
|
||||
rumblelivestreamlib "github.com/tylertravisty/rumble-livestream-lib-go"
|
||||
"github.com/wailsapp/wails/v2/pkg/runtime"
|
||||
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
)
|
||||
|
||||
const (
|
||||
AccountType = "Account"
|
||||
ChannelType = "Channel"
|
||||
)
|
||||
|
||||
// App struct
|
||||
type App struct {
|
||||
api *api.Api
|
||||
clients map[string]*rumblelivestreamlib.Client
|
||||
clientsMu sync.Mutex
|
||||
ctx context.Context
|
||||
services *models.Services
|
||||
logError *log.Logger
|
||||
|
@ -36,6 +46,8 @@ func NewApp() *App {
|
|||
log.Fatal("error initializing log: ", err)
|
||||
}
|
||||
|
||||
app.api = api.NewApi(app.logError, app.logInfo)
|
||||
|
||||
return app
|
||||
}
|
||||
|
||||
|
@ -58,6 +70,7 @@ func (a *App) log() error {
|
|||
// so we can call the runtime methods
|
||||
func (a *App) startup(ctx context.Context) {
|
||||
a.ctx = ctx
|
||||
a.api.Startup(ctx)
|
||||
|
||||
db, err := config.Database()
|
||||
if err != nil {
|
||||
|
@ -85,6 +98,13 @@ func (a *App) startup(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 {
|
||||
err := a.services.Close()
|
||||
if err != nil {
|
||||
|
@ -102,7 +122,7 @@ func (a *App) shutdown(ctx context.Context) {
|
|||
a.logFileMu.Unlock()
|
||||
}
|
||||
|
||||
func (a *App) AddChannel(apiKey string) error {
|
||||
func (a *App) AddPage(apiKey string) error {
|
||||
client := rumblelivestreamlib.Client{StreamKey: apiKey}
|
||||
resp, err := client.Request()
|
||||
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)
|
||||
}
|
||||
if acct == nil {
|
||||
err = a.services.AccountS.Create(&models.Account{
|
||||
_, err = a.services.AccountS.Create(&models.Account{
|
||||
UID: &uid,
|
||||
Username: &username,
|
||||
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 {
|
||||
var err error
|
||||
a.clientsMu.Lock()
|
||||
defer a.clientsMu.Unlock()
|
||||
client, exists := a.clients[username]
|
||||
if exists && client != nil {
|
||||
err = client.Logout()
|
||||
|
@ -207,27 +229,107 @@ func (a *App) Login(username string, password string) error {
|
|||
}
|
||||
cookiesS := string(cookiesB)
|
||||
|
||||
act, err := a.services.AccountS.ByUsername(username)
|
||||
acct, err := a.services.AccountS.ByUsername(username)
|
||||
if err != nil {
|
||||
a.logError.Println("error getting account by username:", err)
|
||||
return fmt.Errorf("Error logging in. Try again.")
|
||||
}
|
||||
if act == nil {
|
||||
act = &models.Account{nil, nil, &username, &cookiesS, nil, nil}
|
||||
err = a.services.AccountS.Create(act)
|
||||
if acct == nil {
|
||||
acct = &models.Account{nil, nil, &username, &cookiesS, nil, nil}
|
||||
id, err := a.services.AccountS.Create(acct)
|
||||
if err != nil {
|
||||
a.logError.Println("error creating account:", err)
|
||||
return fmt.Errorf("Error logging in. Try again.")
|
||||
}
|
||||
acct.ID = &id
|
||||
} else {
|
||||
act.Cookies = &cookiesS
|
||||
err = a.services.AccountS.Update(act)
|
||||
acct.Cookies = &cookiesS
|
||||
err = a.services.AccountS.Update(acct)
|
||||
if err != nil {
|
||||
a.logError.Println("error updating account:", err)
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -247,18 +349,26 @@ type Account struct {
|
|||
}
|
||||
|
||||
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{}
|
||||
|
||||
accountChannels, err := a.services.AccountChannelS.All()
|
||||
if err != nil {
|
||||
a.logError.Println("error getting all account channels:", err)
|
||||
return nil, fmt.Errorf("Error retrieving accounts and channels. Try restarting.")
|
||||
return nil, fmt.Errorf("error querying all account channels: %v", err)
|
||||
}
|
||||
|
||||
for _, ac := range accountChannels {
|
||||
if ac.Account.Username == nil {
|
||||
a.logError.Println("account-channel contains nil account username")
|
||||
return nil, fmt.Errorf("Error retrieving accounts and channels. Try restarting.")
|
||||
return nil, fmt.Errorf("account-channel contains nil account username")
|
||||
}
|
||||
|
||||
act, exists := list[*ac.Account.Username]
|
||||
|
@ -274,3 +384,366 @@ func (a *App) AccountList() (map[string]*Account, error) {
|
|||
|
||||
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 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_red from './icons/eye-red.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 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 logo from './logo/logo.png';
|
||||
|
||||
export const ChevronRight = chevron_right;
|
||||
export const CircleGreenBackground = circle_green_background;
|
||||
export const CircleRedBackground = circle_red_background;
|
||||
export const Eye = eye;
|
||||
export const EyeRed = eye_red;
|
||||
export const EyeSlash = eye_slash;
|
||||
export const Gear = gear_fill;
|
||||
export const Heart = heart;
|
||||
export const Logo = logo;
|
||||
export const Pause = pause;
|
||||
export const Play = play;
|
||||
export const PlusCircle = plus_circle;
|
||||
export const Star = star;
|
||||
export const ThumbsDown = thumbs_down;
|
||||
export const ThumbsUp = thumbs_up;
|
||||
export const XLg = x_lg;
|
|
@ -31,7 +31,7 @@
|
|||
text-decoration: none;
|
||||
/* width: 20%; */
|
||||
height: 40px;
|
||||
width: 70px;
|
||||
min-width: 70px;
|
||||
}
|
||||
|
||||
.modal-button-cancel {
|
||||
|
@ -46,21 +46,35 @@
|
|||
text-decoration: none;
|
||||
/* width: 20%; */
|
||||
height: 40px;
|
||||
width: 70px;
|
||||
min-width: 70px;
|
||||
}
|
||||
|
||||
.modal-button-delete {
|
||||
background-color: transparent;
|
||||
border: 1px solid red;
|
||||
background-color: #f23160;
|
||||
border: 1px solid #f23160;
|
||||
border-radius: 5px;
|
||||
color: red;
|
||||
color: #eee;
|
||||
cursor: pointer;
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
text-decoration: none;
|
||||
/* width: 20%; */
|
||||
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 {
|
||||
|
@ -121,6 +135,20 @@
|
|||
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 {
|
||||
background-color: red;
|
||||
border: none;
|
||||
|
@ -131,7 +159,7 @@
|
|||
font-weight: bold;
|
||||
text-decoration: none;
|
||||
/* width: 20%; */
|
||||
width: 70px;
|
||||
min-width: 70px;
|
||||
}
|
||||
|
||||
.small-modal-container {
|
||||
|
|
|
@ -27,7 +27,14 @@ export function Modal(props) {
|
|||
</button>
|
||||
)}
|
||||
{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}
|
||||
</button>
|
||||
)}
|
||||
|
@ -70,7 +77,7 @@ export function SmallModal(props) {
|
|||
</div>
|
||||
<div className='small-modal-footer'>
|
||||
{props.cancelButton && (
|
||||
<button className='modal-button-cancel' onClick={props.onCancel}>
|
||||
<button className='small-modal-button-cancel' onClick={props.onCancel}>
|
||||
{props.cancelButton}
|
||||
</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 @@
|
|||
|
||||
.channel-sidebar {
|
||||
.page-sidebar {
|
||||
align-items: center;
|
||||
background-color: #061726;
|
||||
display: flex;
|
||||
|
@ -7,18 +6,19 @@
|
|||
justify-content: space-between;
|
||||
height: 100%;
|
||||
padding: 0px 10px;
|
||||
width: 60px;
|
||||
}
|
||||
|
||||
.channel-sidebar-account-list {
|
||||
.page-sidebar-account-list {
|
||||
border-top: 2px solid #273848;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
.channel-sidebar-body {
|
||||
.page-sidebar-body {
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.channel-sidebar-button {
|
||||
.page-sidebar-button {
|
||||
align-items: center;
|
||||
background-color: #061726;
|
||||
border: none;
|
||||
|
@ -27,27 +27,31 @@
|
|||
padding: 0px;
|
||||
}
|
||||
|
||||
.channel-sidebar-button:hover {
|
||||
.page-sidebar-button:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.channel-sidebar-button-icon {
|
||||
.page-sidebar-button-icon {
|
||||
height: 60px;
|
||||
width: 60px;
|
||||
}
|
||||
|
||||
.channel-sidebar-footer {
|
||||
.page-sidebar-footer {
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
.channel-sidebar-icon {
|
||||
.page-sidebar-icon {
|
||||
height: 60px;
|
||||
margin-top: 10px;
|
||||
position: relative;
|
||||
width: 60px;
|
||||
}
|
||||
|
||||
.channel-sidebar-icon-account {
|
||||
.page-sidebar-icon:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.page-sidebar-icon-account {
|
||||
bottom: 0px;
|
||||
height: 24px;
|
||||
left: 36px;
|
||||
|
@ -55,7 +59,7 @@
|
|||
width: 24px;
|
||||
}
|
||||
|
||||
.channel-sidebar-icon-hover {
|
||||
.page-sidebar-icon-hover {
|
||||
background-color: #061726;
|
||||
border-radius: 5px;
|
||||
color: black;
|
||||
|
@ -64,7 +68,7 @@
|
|||
/* transform: translate(75px, -50px); */
|
||||
z-index: 10;
|
||||
}
|
||||
.channel-sidebar-icon-hover:before {
|
||||
.page-sidebar-icon-hover:before {
|
||||
content:"";
|
||||
position: absolute;
|
||||
width: 0;
|
||||
|
@ -75,34 +79,35 @@
|
|||
margin: 7px 0 0 -13px;
|
||||
}
|
||||
|
||||
.channel-sidebar-icon-hover-text {
|
||||
.page-sidebar-icon-hover-text {
|
||||
color: white;
|
||||
font-family: sans-serif;
|
||||
font-weight: bold;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.channel-sidebar-icon-image {
|
||||
.page-sidebar-icon-image {
|
||||
/* border: 3px solid #85c742; */
|
||||
/* border: 3px solid #ec0; */
|
||||
border: 3px solid #f23160;
|
||||
/* border: 3px solid #f23160; */
|
||||
border-radius: 50%;
|
||||
height: 54px;
|
||||
transition: border-radius 0.25s;
|
||||
width: 54px;
|
||||
}
|
||||
|
||||
.channel-sidebar-icon-image:hover {
|
||||
.page-sidebar-icon-image:hover {
|
||||
border-radius: 30%;
|
||||
transition: border-radius 0.25s;
|
||||
}
|
||||
|
||||
.channel-sidebar-icon-initial {
|
||||
.page-sidebar-icon-initial {
|
||||
align-items: center;
|
||||
background-color: #3377cc;
|
||||
/* border: 3px solid #3377cc; */
|
||||
/* border: 3px solid #85c742; */
|
||||
/* border: 3px solid #ec0; */
|
||||
border: 3px solid #f23160;
|
||||
/* border: 3px solid #f23160; */
|
||||
border-radius: 50%;
|
||||
color: #eee;
|
||||
display: flex;
|
||||
|
@ -115,7 +120,7 @@
|
|||
width: 54px;
|
||||
}
|
||||
|
||||
.channel-sidebar-icon-initial:hover {
|
||||
.page-sidebar-icon-initial:hover {
|
||||
border-radius: 30%;
|
||||
transition: border-radius 0.25s;
|
||||
}
|
|
@ -1,17 +1,38 @@
|
|||
import { useEffect, useState } from 'react';
|
||||
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 './ChannelSideBar.css';
|
||||
import {
|
||||
ChevronRight,
|
||||
CircleGreenBackground,
|
||||
CircleRedBackground,
|
||||
Eye,
|
||||
EyeSlash,
|
||||
PlusCircle,
|
||||
} from '../assets';
|
||||
import './PageSideBar.css';
|
||||
|
||||
function ChannelSideBar(props) {
|
||||
function PageSideBar(props) {
|
||||
const [accounts, setAccounts] = useState({});
|
||||
const [error, setError] = useState('');
|
||||
const [addOpen, setAddOpen] = useState(false);
|
||||
const [refresh, setRefresh] = useState(false);
|
||||
const [scrollY, setScrollY] = useState(0);
|
||||
|
||||
useEffect(() => {
|
||||
EventsOn('PageSideBarAccounts', (event) => {
|
||||
setAccounts(event);
|
||||
});
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
AccountList()
|
||||
.then((response) => {
|
||||
|
@ -38,8 +59,17 @@ function ChannelSideBar(props) {
|
|||
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 (
|
||||
<>
|
||||
{addOpen && (
|
||||
<ModalAdd
|
||||
onClose={() => setAddOpen(false)}
|
||||
onRefresh={() => {
|
||||
|
@ -47,18 +77,21 @@ function ChannelSideBar(props) {
|
|||
}}
|
||||
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) => (
|
||||
<AccountChannels
|
||||
account={accounts[account]}
|
||||
key={index}
|
||||
openAccount={openAccount}
|
||||
openChannel={openChannel}
|
||||
scrollY={scrollY}
|
||||
top={index === 0}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
<div className='channel-sidebar-footer'>
|
||||
<div className='page-sidebar-footer'>
|
||||
<ButtonIcon
|
||||
hoverText={'Add an account/channel'}
|
||||
onClick={() => setAddOpen(true)}
|
||||
|
@ -70,7 +103,7 @@ function ChannelSideBar(props) {
|
|||
);
|
||||
}
|
||||
|
||||
export default ChannelSideBar;
|
||||
export default PageSideBar;
|
||||
|
||||
function AccountChannels(props) {
|
||||
const sortChannels = () => {
|
||||
|
@ -84,12 +117,24 @@ function AccountChannels(props) {
|
|||
if (props.account.account !== undefined) {
|
||||
return (
|
||||
<div
|
||||
className='channel-sidebar-account-list'
|
||||
className='page-sidebar-account-list'
|
||||
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) => (
|
||||
<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>
|
||||
);
|
||||
|
@ -97,25 +142,82 @@ function AccountChannels(props) {
|
|||
}
|
||||
|
||||
function AccountIcon(props) {
|
||||
const [apiActive, setApiActive] = 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 (
|
||||
<div
|
||||
className='channel-sidebar-icon'
|
||||
className='page-sidebar-icon'
|
||||
onMouseEnter={() => setHover(true)}
|
||||
onMouseLeave={() => setHover(false)}
|
||||
>
|
||||
{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()}
|
||||
</span>
|
||||
) : (
|
||||
<img className='channel-sidebar-icon-image' src={props.account.profile_image} />
|
||||
)}
|
||||
<img className='channel-sidebar-icon-account' src={CircleGreenBackground} />
|
||||
{hover && (
|
||||
<HoverName name={'/user/' + props.account.username} scrollY={props.scrollY} />
|
||||
<img
|
||||
className='page-sidebar-icon-image'
|
||||
src={props.account.profile_image}
|
||||
style={{ border: iconBorder() }}
|
||||
/>
|
||||
)}
|
||||
<img
|
||||
className='page-sidebar-icon-account'
|
||||
src={loggedIn ? CircleGreenBackground : CircleRedBackground}
|
||||
/>
|
||||
{hover && <HoverName name={pageName(username)} scrollY={props.scrollY} />}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -125,12 +227,12 @@ function ButtonIcon(props) {
|
|||
|
||||
return (
|
||||
<div
|
||||
className='channel-sidebar-icon'
|
||||
className='page-sidebar-icon'
|
||||
onMouseEnter={() => setHover(true)}
|
||||
onMouseLeave={() => setHover(false)}
|
||||
>
|
||||
<button className='channel-sidebar-button' onClick={props.onClick}>
|
||||
<img className='channel-sidebar-button-icon' src={PlusCircle} />
|
||||
<button className='page-sidebar-button' onClick={props.onClick}>
|
||||
<img className='page-sidebar-button-icon' src={PlusCircle} />
|
||||
</button>
|
||||
{hover && <HoverName name={props.hoverText} scrollY={props.scrollY} />}
|
||||
</div>
|
||||
|
@ -138,26 +240,69 @@ function ButtonIcon(props) {
|
|||
}
|
||||
|
||||
function ChannelIcon(props) {
|
||||
const [apiActive, setApiActive] = useState(false);
|
||||
const [channelName, setChannelName] = useState(props.channel.name);
|
||||
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 (
|
||||
<div
|
||||
className='channel-sidebar-icon'
|
||||
className='page-sidebar-icon'
|
||||
onMouseEnter={() => setHover(true)}
|
||||
onMouseLeave={() => setHover(false)}
|
||||
>
|
||||
{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()}
|
||||
</span>
|
||||
) : (
|
||||
<img className='channel-sidebar-icon-image' src={props.channel.profile_image} />
|
||||
)}
|
||||
{hover && (
|
||||
<HoverName
|
||||
name={'/c/' + props.channel.name.replace(/\s/g, '')}
|
||||
scrollY={props.scrollY}
|
||||
<img
|
||||
className='page-sidebar-icon-image'
|
||||
src={props.channel.profile_image}
|
||||
style={{ border: iconBorder() }}
|
||||
/>
|
||||
)}
|
||||
{hover && <HoverName name={pageName(channelName)} scrollY={props.scrollY} />}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -165,10 +310,10 @@ function ChannelIcon(props) {
|
|||
function HoverName(props) {
|
||||
return (
|
||||
<div
|
||||
className='channel-sidebar-icon-hover'
|
||||
className='page-sidebar-icon-hover'
|
||||
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>
|
||||
);
|
||||
}
|
||||
|
@ -220,7 +365,7 @@ function ModalAdd(props) {
|
|||
|
||||
useEffect(() => {
|
||||
if (addChannelLoading) {
|
||||
AddChannel(channelKey)
|
||||
AddPage(channelKey)
|
||||
.then(() => {
|
||||
reset();
|
||||
props.onClose();
|
||||
|
@ -318,6 +463,7 @@ function ModalAdd(props) {
|
|||
|
||||
return (
|
||||
<>
|
||||
{error !== '' && (
|
||||
<SmallModal
|
||||
onClose={() => setError('')}
|
||||
show={error !== ''}
|
||||
|
@ -327,6 +473,7 @@ function ModalAdd(props) {
|
|||
submitButton={'OK'}
|
||||
onSubmit={() => setError('')}
|
||||
/>
|
||||
)}
|
||||
<Modal
|
||||
cancelButton={stage !== 'start' ? 'Back' : ''}
|
||||
onCancel={back}
|
|
@ -1,12 +1,16 @@
|
|||
import { useState } from 'react';
|
||||
|
||||
import { CircleGreenBackground, Heart } from '../assets';
|
||||
import ChannelSideBar from '../components/ChannelSideBar';
|
||||
import PageDetails from '../components/PageDetails';
|
||||
import PageSideBar from '../components/PageSideBar';
|
||||
import './Dashboard.css';
|
||||
|
||||
function Dashboard() {
|
||||
return (
|
||||
<div className='dashboard'>
|
||||
<ChannelSideBar />
|
||||
<div style={{ backgroundColor: '#1f2e3c', width: '100%', height: '100%' }}></div>
|
||||
<PageSideBar />
|
||||
<PageDetails />
|
||||
<div style={{ backgroundColor: '#344453', width: '100%', height: '100%' }}></div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
10
v1/go.mod
|
@ -6,7 +6,7 @@ toolchain go1.22.0
|
|||
|
||||
require (
|
||||
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
|
||||
)
|
||||
|
||||
|
@ -28,7 +28,7 @@ require (
|
|||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/r3labs/sse/v2 v2.10.0 // 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/tkrajina/go-reflector v0.5.6 // 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/wailsapp/go-webview2 v1.0.10 // 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/net v0.20.0 // indirect
|
||||
golang.org/x/sys v0.16.0 // indirect
|
||||
golang.org/x/net v0.22.0 // indirect
|
||||
golang.org/x/sys v0.18.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
gopkg.in/cenkalti/backoff.v1 v1.1.0 // 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.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis=
|
||||
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.2.1/go.mod h1:UPwtJ1Xu7JrLcZjNWN8orJaM5n5YEtqL//farB5FlRY=
|
||||
github.com/robertkrimen/otto v0.3.0 h1:5RI+8860NSxvXywDY9ddF5HcPw0puRsd8EgbXV0oqRE=
|
||||
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/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA=
|
||||
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/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/rumble-livestream-lib-go v0.3.4 h1:VPKelrC3hesJlbqdByMkUhbEubFx80T5FNC60JKrEfw=
|
||||
github.com/tylertravisty/rumble-livestream-lib-go v0.3.4/go.mod h1:rUET5uInouMfB4ekqdGiYeoN5ibOdzU9cCgRE0i57Wg=
|
||||
github.com/tylertravisty/rumble-livestream-lib-go v0.3.5 h1:mAf4oYuQ55pXTPsIMVztOlYM8oGsBgsNMJvel2VLgsQ=
|
||||
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/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||
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/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.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
|
||||
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
|
||||
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
|
||||
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/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-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
|
||||
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
|
||||
golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc=
|
||||
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-20190916202348-b4ddaad3f8a3/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-20220811171246-fbc7d0a398ab/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.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
|
||||
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/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
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"`
|
||||
}
|
||||
|
||||
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 {
|
||||
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 {
|
||||
All() ([]Account, error)
|
||||
AutoMigrate() error
|
||||
ByID(id int64) (*Account, error)
|
||||
ByUsername(username string) (*Account, error)
|
||||
Create(a *Account) error
|
||||
Create(a *Account) (int64, error)
|
||||
Delete(a *Account) error
|
||||
DestructiveReset() error
|
||||
Update(a *Account) error
|
||||
}
|
||||
|
@ -138,6 +169,34 @@ func (as *accountService) createAccountTable() error {
|
|||
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) {
|
||||
err := runAccountValFuncs(
|
||||
&Account{Username: &username},
|
||||
|
@ -166,24 +225,50 @@ func (as *accountService) ByUsername(username string) (*Account, error) {
|
|||
return sa.toAccount(), nil
|
||||
}
|
||||
|
||||
func (as *accountService) Create(a *Account) error {
|
||||
func (as *accountService) Create(a *Account) (int64, error) {
|
||||
err := runAccountValFuncs(
|
||||
a,
|
||||
accountRequireUsername,
|
||||
)
|
||||
if err != nil {
|
||||
return pkgErr("invalid account", err)
|
||||
return -1, pkgErr("invalid account", err)
|
||||
}
|
||||
|
||||
columns := columnsNoID(accountColumns)
|
||||
insertQ := fmt.Sprintf(`
|
||||
INSERT INTO "%s" (%s)
|
||||
VALUES (%s)
|
||||
RETURNING id
|
||||
`, 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 {
|
||||
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
|
||||
|
@ -230,7 +315,7 @@ func (as *accountService) Update(a *Account) error {
|
|||
|
||||
_, err = as.Database.Exec(updateQ, a.valuesEndID()...)
|
||||
if err != nil {
|
||||
return pkgErr(fmt.Sprintf("error executing update query", accountTable), err)
|
||||
return pkgErr("error executing update query", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
@ -3,6 +3,7 @@ package models
|
|||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -19,6 +20,35 @@ type Channel struct {
|
|||
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 {
|
||||
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 {
|
||||
AutoMigrate() error
|
||||
ByAccount(a *Account) ([]Channel, error)
|
||||
ByID(id int64) (*Channel, error)
|
||||
ByName(name string) (*Channel, error)
|
||||
Create(c *Channel) error
|
||||
Delete(c *Channel) error
|
||||
DestructiveReset() error
|
||||
Update(c *Channel) error
|
||||
}
|
||||
|
||||
func NewChannelService(db *sql.DB) ChannelService {
|
||||
|
@ -106,6 +140,74 @@ func (cs *channelService) createChannelTable() error {
|
|||
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) {
|
||||
err := runChannelValFuncs(
|
||||
&Channel{Name: &name},
|
||||
|
@ -160,6 +262,28 @@ func (cs *channelService) Create(c *Channel) error {
|
|||
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 {
|
||||
err := cs.dropChannelTable()
|
||||
if err != nil {
|
||||
|
@ -182,6 +306,33 @@ func (cs *channelService) dropChannelTable() error {
|
|||
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
|
||||
|
||||
func runChannelValFuncs(c *Channel, fns ...channelValFunc) error {
|
||||
|
@ -215,6 +366,14 @@ func channelRequireApiKey(c *Channel) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func channelRequireID(c *Channel) error {
|
||||
if c.ID == nil || *c.ID < 1 {
|
||||
return ErrChannelInvalidID
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func channelRequireCID(c *Channel) error {
|
||||
if c.CID == nil || *c.CID == "" {
|
||||
return ErrChannelInvalidCID
|
||||
|
|
|
@ -11,6 +11,7 @@ const (
|
|||
ErrChannelInvalidAccountID ValidatorError = "invalid channel account id"
|
||||
ErrChannelInvalidApiKey ValidatorError = "invalid channel API key"
|
||||
ErrChannelInvalidCID ValidatorError = "invalid channel CID"
|
||||
ErrChannelInvalidID ValidatorError = "invalid channel ID"
|
||||
ErrChannelInvalidName ValidatorError = "invalid channel name"
|
||||
)
|
||||
|
||||
|
|
13
v1/vendor/github.com/robertkrimen/otto/.gitignore
generated
vendored
|
@ -1,7 +1,10 @@
|
|||
/.test
|
||||
/otto/otto
|
||||
/otto/otto-*
|
||||
/test/test-*.js
|
||||
/test/tester
|
||||
.test
|
||||
otto/otto
|
||||
otto/otto-*
|
||||
tools/tester/testdata/
|
||||
tools/tester/tester
|
||||
tools/gen-jscore/gen-jscore
|
||||
tools/gen-tokens/gen-tokens
|
||||
.idea
|
||||
dist/
|
||||
.vscode/
|
||||
|
|
48
v1/vendor/github.com/robertkrimen/otto/.golangci.yml
generated
vendored
|
@ -4,6 +4,7 @@ run:
|
|||
- terst
|
||||
skip-files:
|
||||
- dbg/dbg.go
|
||||
- token/token_const.go
|
||||
|
||||
linters-settings:
|
||||
govet:
|
||||
|
@ -11,25 +12,17 @@ linters-settings:
|
|||
goconst:
|
||||
min-len: 2
|
||||
min-occurrences: 4
|
||||
revive:
|
||||
enable-all-rules: false
|
||||
rules:
|
||||
- name: var-naming
|
||||
disabled: true
|
||||
|
||||
linters:
|
||||
enable-all: true
|
||||
disable:
|
||||
- dupl
|
||||
- gas
|
||||
- errcheck
|
||||
- gofmt
|
||||
- gosimple
|
||||
- interfacer
|
||||
- megacheck
|
||||
- maligned
|
||||
- structcheck
|
||||
- staticcheck
|
||||
- unconvert
|
||||
- unparam
|
||||
- varcheck
|
||||
- lll
|
||||
- prealloc
|
||||
- gochecknoglobals
|
||||
- gochecknoinits
|
||||
- scopelint
|
||||
|
@ -39,35 +32,34 @@ linters:
|
|||
- goerr113
|
||||
- wsl
|
||||
- nlreturn
|
||||
- tagliatelle
|
||||
- gomnd
|
||||
- paralleltest
|
||||
- wrapcheck
|
||||
- testpackage
|
||||
- golint
|
||||
- gofumpt
|
||||
- forbidigo
|
||||
- gocognit
|
||||
- gocritic
|
||||
- godot
|
||||
- nakedret
|
||||
- nestif
|
||||
- revive
|
||||
- errorlint
|
||||
- exhaustive
|
||||
- forcetypeassert
|
||||
- ifshort
|
||||
- stylecheck
|
||||
- gocyclo
|
||||
- misspell
|
||||
- cyclop
|
||||
- varnamelen
|
||||
- nonamedreturns
|
||||
- maintidx
|
||||
- ireturn
|
||||
- exhaustruct
|
||||
- nosnakecase
|
||||
- deadcode
|
||||
- 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"
|
||||
)
|
||||
|
||||
// CommentPosition determines where the comment is in a given context
|
||||
// CommentPosition determines where the comment is in a given context.
|
||||
type CommentPosition int
|
||||
|
||||
// Available comment positions.
|
||||
const (
|
||||
_ CommentPosition = iota
|
||||
LEADING // Before the pertinent expression
|
||||
TRAILING // After the pertinent expression
|
||||
KEY // Before a key in an object
|
||||
COLON // After a colon in a field declaration
|
||||
FINAL // Final comments in a block, not belonging to a specific expression or the comment after a trailing , in an array or object literal
|
||||
IF // After an if keyword
|
||||
WHILE // After a while keyword
|
||||
DO // After do keyword
|
||||
FOR // After a for keyword
|
||||
WITH // After a with keyword
|
||||
// LEADING is before the pertinent expression.
|
||||
LEADING
|
||||
// TRAILING is after the pertinent expression.
|
||||
TRAILING
|
||||
// KEY is before a key in an object.
|
||||
KEY
|
||||
// COLON is after a colon in a field declaration.
|
||||
COLON
|
||||
// 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.
|
||||
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
|
||||
)
|
||||
|
||||
// Comment contains the data of the comment
|
||||
// Comment contains the data of the comment.
|
||||
type Comment struct {
|
||||
Begin file.Idx
|
||||
Text string
|
||||
Position CommentPosition
|
||||
}
|
||||
|
||||
// NewComment creates a new comment
|
||||
// NewComment creates a new comment.
|
||||
func NewComment(text string, idx file.Idx) *Comment {
|
||||
comment := &Comment{
|
||||
Begin: idx,
|
||||
|
@ -42,7 +54,7 @@ func NewComment(text string, idx file.Idx) *Comment {
|
|||
return comment
|
||||
}
|
||||
|
||||
// String returns a stringified version of the position
|
||||
// String returns a stringified version of the position.
|
||||
func (cp CommentPosition) String() string {
|
||||
switch cp {
|
||||
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 {
|
||||
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 {
|
||||
// CommentMap is a reference to the parser comment map
|
||||
CommentMap CommentMap
|
||||
// Comments lists the comments scanned, not linked to a node yet
|
||||
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 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
|
||||
// primary determines whether or not processing a primary expression
|
||||
primary bool
|
||||
|
@ -94,6 +106,7 @@ type Comments struct {
|
|||
afterBlock bool
|
||||
}
|
||||
|
||||
// NewComments returns a new Comments.
|
||||
func NewComments() *Comments {
|
||||
comments := &Comments{
|
||||
CommentMap: CommentMap{},
|
||||
|
@ -107,7 +120,7 @@ func (c *Comments) String() string {
|
|||
}
|
||||
|
||||
// FetchAll returns all the currently scanned comments,
|
||||
// including those from the next line
|
||||
// including those from the next line.
|
||||
func (c *Comments) FetchAll() []*Comment {
|
||||
defer func() {
|
||||
c.Comments = nil
|
||||
|
@ -117,7 +130,7 @@ func (c *Comments) FetchAll() []*Comment {
|
|||
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 {
|
||||
defer func() {
|
||||
c.Comments = nil
|
||||
|
@ -126,12 +139,12 @@ func (c *Comments) Fetch() []*Comment {
|
|||
return c.Comments
|
||||
}
|
||||
|
||||
// ResetLineBreak marks the beginning of a new statement
|
||||
// ResetLineBreak marks the beginning of a new statement.
|
||||
func (c *Comments) ResetLineBreak() {
|
||||
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() {
|
||||
c.primary = true
|
||||
c.wasLineBreak = false
|
||||
|
@ -205,7 +218,7 @@ func (c *Comments) SetExpression(node Expression) {
|
|||
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) {
|
||||
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() {
|
||||
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
|
||||
|
||||
// AddComment adds a single comment to the map
|
||||
// AddComment adds a single comment to the map.
|
||||
func (cm CommentMap) AddComment(node Node, comment *Comment) {
|
||||
list := cm[node]
|
||||
list = append(list, comment)
|
||||
|
@ -244,7 +257,7 @@ func (cm CommentMap) AddComment(node Node, comment *Comment) {
|
|||
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) {
|
||||
for _, comment := range comments {
|
||||
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 {
|
||||
size := 0
|
||||
for _, comments := range cm {
|
||||
|
@ -264,7 +277,7 @@ func (cm CommentMap) Size() int {
|
|||
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) {
|
||||
for i, c := range cm[from] {
|
||||
if c.Position == position {
|
||||
|
|
1051
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)
|
||||
}
|
||||
case *BadExpression:
|
||||
case *BadStatement:
|
||||
case *BinaryExpression:
|
||||
if n != nil {
|
||||
Walk(v, n.Left)
|
||||
|
|
118
v1/vendor/github.com/robertkrimen/otto/builtin.go
generated
vendored
|
@ -2,6 +2,7 @@ package otto
|
|||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"math"
|
||||
"net/url"
|
||||
"regexp"
|
||||
|
@ -11,34 +12,34 @@ import (
|
|||
"unicode/utf8"
|
||||
)
|
||||
|
||||
// Global
|
||||
func builtinGlobal_eval(call FunctionCall) Value {
|
||||
// Global.
|
||||
func builtinGlobalEval(call FunctionCall) Value {
|
||||
src := call.Argument(0)
|
||||
if !src.IsString() {
|
||||
return src
|
||||
}
|
||||
runtime := call.runtime
|
||||
program := runtime.cmpl_parseOrThrow(src.string(), nil)
|
||||
rt := call.runtime
|
||||
program := rt.cmplParseOrThrow(src.string(), nil)
|
||||
if !call.eval {
|
||||
// Not a direct call to eval, so we enter the global ExecutionContext
|
||||
runtime.enterGlobalScope()
|
||||
defer runtime.leaveScope()
|
||||
rt.enterGlobalScope()
|
||||
defer rt.leaveScope()
|
||||
}
|
||||
returnValue := runtime.cmpl_evaluate_nodeProgram(program, true)
|
||||
returnValue := rt.cmplEvaluateNodeProgram(program, true)
|
||||
if returnValue.isEmpty() {
|
||||
return Value{}
|
||||
}
|
||||
return returnValue
|
||||
}
|
||||
|
||||
func builtinGlobal_isNaN(call FunctionCall) Value {
|
||||
func builtinGlobalIsNaN(call FunctionCall) Value {
|
||||
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()
|
||||
return toValue_bool(!math.IsNaN(value) && !math.IsInf(value, 0))
|
||||
return boolValue(!math.IsNaN(value) && !math.IsInf(value, 0))
|
||||
}
|
||||
|
||||
func digitValue(chr rune) int {
|
||||
|
@ -53,8 +54,8 @@ func digitValue(chr rune) int {
|
|||
return 36 // Larger than any legal digit value
|
||||
}
|
||||
|
||||
func builtinGlobal_parseInt(call FunctionCall) Value {
|
||||
input := strings.Trim(call.Argument(0).string(), builtinString_trim_whitespace)
|
||||
func builtinGlobalParseInt(call FunctionCall) Value {
|
||||
input := strings.Trim(call.Argument(0).string(), builtinStringTrimWhitespace)
|
||||
if len(input) == 0 {
|
||||
return NaNValue()
|
||||
}
|
||||
|
@ -106,7 +107,7 @@ func builtinGlobal_parseInt(call FunctionCall) Value {
|
|||
|
||||
value, err := strconv.ParseInt(input, radix, 64)
|
||||
if err != nil {
|
||||
if err.(*strconv.NumError).Err == strconv.ErrRange {
|
||||
if errors.Is(err, strconv.ErrRange) {
|
||||
base := float64(base)
|
||||
// Could just be a very large number (e.g. 0x8000000000000000)
|
||||
var value float64
|
||||
|
@ -120,7 +121,7 @@ func builtinGlobal_parseInt(call FunctionCall) Value {
|
|||
if negative {
|
||||
value *= -1
|
||||
}
|
||||
return toValue_float64(value)
|
||||
return float64Value(value)
|
||||
}
|
||||
return NaNValue()
|
||||
}
|
||||
|
@ -128,24 +129,26 @@ func builtinGlobal_parseInt(call FunctionCall) Value {
|
|||
value *= -1
|
||||
}
|
||||
|
||||
return toValue_int64(value)
|
||||
return int64Value(value)
|
||||
}
|
||||
|
||||
var parseFloat_matchBadSpecial = regexp.MustCompile(`[\+\-]?(?:[Ii]nf$|infinity)`)
|
||||
var parseFloat_matchValid = regexp.MustCompile(`[0-9eE\+\-\.]|Infinity`)
|
||||
var (
|
||||
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
|
||||
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()
|
||||
}
|
||||
value, err := strconv.ParseFloat(input, 64)
|
||||
if err != nil {
|
||||
for end := len(input); end > 0; end-- {
|
||||
input := input[0:end]
|
||||
if !parseFloat_matchValid.MatchString(input) {
|
||||
if !parseFloatMatchValid.MatchString(input) {
|
||||
return NaNValue()
|
||||
}
|
||||
value, err = strconv.ParseFloat(input, 64)
|
||||
|
@ -157,12 +160,12 @@ func builtinGlobal_parseFloat(call FunctionCall) Value {
|
|||
return NaNValue()
|
||||
}
|
||||
}
|
||||
return toValue_float64(value)
|
||||
return float64Value(value)
|
||||
}
|
||||
|
||||
// encodeURI/decodeURI
|
||||
|
||||
func _builtinGlobal_encodeURI(call FunctionCall, escape *regexp.Regexp) Value {
|
||||
func encodeDecodeURI(call FunctionCall, escape *regexp.Regexp) Value {
|
||||
value := call.Argument(0)
|
||||
var input []uint16
|
||||
switch vl := value.value.(type) {
|
||||
|
@ -172,7 +175,7 @@ func _builtinGlobal_encodeURI(call FunctionCall, escape *regexp.Regexp) Value {
|
|||
input = utf16.Encode([]rune(value.string()))
|
||||
}
|
||||
if len(input) == 0 {
|
||||
return toValue_string("")
|
||||
return stringValue("")
|
||||
}
|
||||
output := []byte{}
|
||||
length := len(input)
|
||||
|
@ -184,7 +187,7 @@ func _builtinGlobal_encodeURI(call FunctionCall, escape *regexp.Regexp) Value {
|
|||
panic(call.runtime.panicURIError("URI malformed"))
|
||||
}
|
||||
if value >= 0xD800 && value <= 0xDBFF {
|
||||
index += 1
|
||||
index++
|
||||
if index >= length {
|
||||
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}
|
||||
}
|
||||
index += 1
|
||||
index++
|
||||
size := utf8.EncodeRune(encode, decode[0])
|
||||
encode := encode[0:size]
|
||||
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
|
||||
if target[0] == ' ' {
|
||||
return []byte("%20")
|
||||
}
|
||||
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 {
|
||||
return _builtinGlobal_encodeURI(call, encodeURI_Regexp)
|
||||
func builtinGlobalEncodeURI(call FunctionCall) Value {
|
||||
return encodeDecodeURI(call, encodeURIRegexp)
|
||||
}
|
||||
|
||||
var encodeURIComponent_Regexp = regexp.MustCompile(`([^~!*()'])`)
|
||||
var encodeURIComponentRegexp = regexp.MustCompile(`([^~!*()'])`)
|
||||
|
||||
func builtinGlobal_encodeURIComponent(call FunctionCall) Value {
|
||||
return _builtinGlobal_encodeURI(call, encodeURIComponent_Regexp)
|
||||
func builtinGlobalEncodeURIComponent(call FunctionCall) Value {
|
||||
return encodeDecodeURI(call, encodeURIComponentRegexp)
|
||||
}
|
||||
|
||||
// 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)`)
|
||||
// 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 {
|
||||
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)
|
||||
if err != nil || !utf8.ValidString(output) {
|
||||
return "", true
|
||||
|
@ -239,25 +241,25 @@ func _decodeURI(input string, reserve bool) (string, bool) {
|
|||
return output, false
|
||||
}
|
||||
|
||||
func builtinGlobal_decodeURI(call FunctionCall) Value {
|
||||
output, err := _decodeURI(call.Argument(0).string(), true)
|
||||
func builtinGlobalDecodeURI(call FunctionCall) Value {
|
||||
output, err := decodeURI(call.Argument(0).string(), true)
|
||||
if err {
|
||||
panic(call.runtime.panicURIError("URI malformed"))
|
||||
}
|
||||
return toValue_string(output)
|
||||
return stringValue(output)
|
||||
}
|
||||
|
||||
func builtinGlobal_decodeURIComponent(call FunctionCall) Value {
|
||||
output, err := _decodeURI(call.Argument(0).string(), false)
|
||||
func builtinGlobalDecodeURIComponent(call FunctionCall) Value {
|
||||
output, err := decodeURI(call.Argument(0).string(), false)
|
||||
if err {
|
||||
panic(call.runtime.panicURIError("URI malformed"))
|
||||
}
|
||||
return toValue_string(output)
|
||||
return stringValue(output)
|
||||
}
|
||||
|
||||
// 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' {
|
||||
return false
|
||||
}
|
||||
|
@ -266,11 +268,11 @@ func builtin_shouldEscape(chr byte) bool {
|
|||
|
||||
const escapeBase16 = "0123456789ABCDEF"
|
||||
|
||||
func builtin_escape(input string) string {
|
||||
func builtinEscape(input string) string {
|
||||
output := make([]byte, 0, len(input))
|
||||
length := len(input)
|
||||
for index := 0; index < length; {
|
||||
if builtin_shouldEscape(input[index]) {
|
||||
if builtinShouldEscape(input[index]) {
|
||||
chr, width := utf8.DecodeRuneInString(input[index:])
|
||||
chr16 := utf16.Encode([]rune{chr})[0]
|
||||
if 256 > chr16 {
|
||||
|
@ -289,13 +291,13 @@ func builtin_escape(input string) string {
|
|||
index += width
|
||||
} else {
|
||||
output = append(output, input[index])
|
||||
index += 1
|
||||
index++
|
||||
}
|
||||
}
|
||||
return string(output)
|
||||
}
|
||||
|
||||
func builtin_unescape(input string) string {
|
||||
func builtinUnescape(input string) string {
|
||||
output := make([]rune, 0, len(input))
|
||||
length := len(input)
|
||||
for index := 0; index < length; {
|
||||
|
@ -322,15 +324,15 @@ func builtin_unescape(input string) string {
|
|||
}
|
||||
}
|
||||
output = append(output, rune(input[index]))
|
||||
index += 1
|
||||
index++
|
||||
}
|
||||
return string(output)
|
||||
}
|
||||
|
||||
func builtinGlobal_escape(call FunctionCall) Value {
|
||||
return toValue_string(builtin_escape(call.Argument(0).string()))
|
||||
func builtinGlobalEscape(call FunctionCall) Value {
|
||||
return stringValue(builtinEscape(call.Argument(0).string()))
|
||||
}
|
||||
|
||||
func builtinGlobal_unescape(call FunctionCall) Value {
|
||||
return toValue_string(builtin_unescape(call.Argument(0).string()))
|
||||
func builtinGlobalUnescape(call FunctionCall) Value {
|
||||
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
|
||||
|
||||
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 {
|
||||
return toValue_object(builtinNewArrayNative(self.runtime, argumentList))
|
||||
func builtinNewArray(obj *object, argumentList []Value) Value {
|
||||
return objectValue(builtinNewArrayNative(obj.runtime, argumentList))
|
||||
}
|
||||
|
||||
func builtinNewArrayNative(runtime *_runtime, argumentList []Value) *_object {
|
||||
func builtinNewArrayNative(rt *runtime, argumentList []Value) *object {
|
||||
if len(argumentList) == 1 {
|
||||
firstArgument := argumentList[0]
|
||||
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()
|
||||
join := thisObject.get("join")
|
||||
if join.isCallable() {
|
||||
join := join._object()
|
||||
join := join.object()
|
||||
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 := ","
|
||||
thisObject := call.thisObject()
|
||||
length := int64(toUint32(thisObject.get(propertyLength)))
|
||||
if length == 0 {
|
||||
return toValue_string("")
|
||||
return stringValue("")
|
||||
}
|
||||
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))
|
||||
stringValue := ""
|
||||
switch value.kind {
|
||||
case valueEmpty, valueUndefined, valueNull:
|
||||
default:
|
||||
object := call.runtime.toObject(value)
|
||||
toLocaleString := object.get("toLocaleString")
|
||||
obj := call.runtime.toObject(value)
|
||||
toLocaleString := obj.get("toLocaleString")
|
||||
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)
|
||||
}
|
||||
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()
|
||||
valueArray := []Value{}
|
||||
source := append([]Value{toValue_object(thisObject)}, call.ArgumentList...)
|
||||
source := append([]Value{objectValue(thisObject)}, call.ArgumentList...)
|
||||
for _, item := range source {
|
||||
switch item.kind {
|
||||
case valueObject:
|
||||
object := item._object()
|
||||
if isArray(object) {
|
||||
length := object.get(propertyLength).number().int64
|
||||
for index := int64(0); index < length; index += 1 {
|
||||
obj := item.object()
|
||||
if isArray(obj) {
|
||||
length := obj.get(propertyLength).number().int64
|
||||
for index := int64(0); index < length; index++ {
|
||||
name := strconv.FormatInt(index, 10)
|
||||
if object.hasProperty(name) {
|
||||
valueArray = append(valueArray, object.get(name))
|
||||
if obj.hasProperty(name) {
|
||||
valueArray = append(valueArray, obj.get(name))
|
||||
} else {
|
||||
valueArray = append(valueArray, Value{})
|
||||
}
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
fallthrough
|
||||
default:
|
||||
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()
|
||||
length := int64(toUint32(thisObject.get(propertyLength)))
|
||||
if 0 == length {
|
||||
thisObject.put(propertyLength, toValue_int64(0), true)
|
||||
if length == 0 {
|
||||
thisObject.put(propertyLength, int64Value(0), true)
|
||||
return Value{}
|
||||
}
|
||||
first := thisObject.get("0")
|
||||
|
@ -107,52 +108,50 @@ func builtinArray_shift(call FunctionCall) Value {
|
|||
}
|
||||
}
|
||||
thisObject.delete(arrayIndexToString(length-1), true)
|
||||
thisObject.put(propertyLength, toValue_int64(length-1), true)
|
||||
thisObject.put(propertyLength, int64Value(length-1), true)
|
||||
return first
|
||||
}
|
||||
|
||||
func builtinArray_push(call FunctionCall) Value {
|
||||
func builtinArrayPush(call FunctionCall) Value {
|
||||
thisObject := call.thisObject()
|
||||
itemList := call.ArgumentList
|
||||
index := int64(toUint32(thisObject.get(propertyLength)))
|
||||
for len(itemList) > 0 {
|
||||
thisObject.put(arrayIndexToString(index), itemList[0], true)
|
||||
itemList = itemList[1:]
|
||||
index += 1
|
||||
index++
|
||||
}
|
||||
length := toValue_int64(index)
|
||||
length := int64Value(index)
|
||||
thisObject.put(propertyLength, length, true)
|
||||
return length
|
||||
}
|
||||
|
||||
func builtinArray_pop(call FunctionCall) Value {
|
||||
func builtinArrayPop(call FunctionCall) Value {
|
||||
thisObject := call.thisObject()
|
||||
length := int64(toUint32(thisObject.get(propertyLength)))
|
||||
if 0 == length {
|
||||
thisObject.put(propertyLength, toValue_uint32(0), true)
|
||||
if length == 0 {
|
||||
thisObject.put(propertyLength, uint32Value(0), true)
|
||||
return Value{}
|
||||
}
|
||||
last := thisObject.get(arrayIndexToString(length - 1))
|
||||
thisObject.delete(arrayIndexToString(length-1), true)
|
||||
thisObject.put(propertyLength, toValue_int64(length-1), true)
|
||||
thisObject.put(propertyLength, int64Value(length-1), true)
|
||||
return last
|
||||
}
|
||||
|
||||
func builtinArray_join(call FunctionCall) Value {
|
||||
func builtinArrayJoin(call FunctionCall) Value {
|
||||
separator := ","
|
||||
{
|
||||
argument := call.Argument(0)
|
||||
if argument.IsDefined() {
|
||||
separator = argument.string()
|
||||
}
|
||||
}
|
||||
thisObject := call.thisObject()
|
||||
length := int64(toUint32(thisObject.get(propertyLength)))
|
||||
if length == 0 {
|
||||
return toValue_string("")
|
||||
return stringValue("")
|
||||
}
|
||||
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))
|
||||
stringValue := ""
|
||||
switch value.kind {
|
||||
|
@ -162,10 +161,10 @@ func builtinArray_join(call FunctionCall) Value {
|
|||
}
|
||||
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()
|
||||
length := int64(toUint32(thisObject.get(propertyLength)))
|
||||
|
||||
|
@ -177,7 +176,7 @@ func builtinArray_splice(call FunctionCall) Value {
|
|||
valueArray := make([]Value, deleteCount)
|
||||
|
||||
for index := int64(0); index < deleteCount; index++ {
|
||||
indexString := arrayIndexToString(int64(start + index))
|
||||
indexString := arrayIndexToString(start + index)
|
||||
if thisObject.hasProperty(indexString) {
|
||||
valueArray[index] = thisObject.get(indexString)
|
||||
}
|
||||
|
@ -197,7 +196,7 @@ func builtinArray_splice(call FunctionCall) Value {
|
|||
}
|
||||
if itemCount < deleteCount {
|
||||
// The Object/Array is shrinking
|
||||
stop := int64(length) - deleteCount
|
||||
stop := length - deleteCount
|
||||
// The new length of the Object/Array before
|
||||
// appending the itemList remainder
|
||||
// Stopping at the lower bound of the insertion:
|
||||
|
@ -215,7 +214,7 @@ func builtinArray_splice(call FunctionCall) Value {
|
|||
// Delete off the end
|
||||
// We don't bother to delete below <stop + itemCount> (if any) since those
|
||||
// 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)
|
||||
}
|
||||
} else if itemCount > deleteCount {
|
||||
|
@ -226,7 +225,7 @@ func builtinArray_splice(call FunctionCall) Value {
|
|||
// Starting from the upper bound of the deletion:
|
||||
// Move an item from the after the deleted 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)
|
||||
to := arrayIndexToString(index + itemCount - 1)
|
||||
if thisObject.hasProperty(from) {
|
||||
|
@ -240,12 +239,12 @@ func builtinArray_splice(call FunctionCall) Value {
|
|||
for index := int64(0); index < itemCount; index++ {
|
||||
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()
|
||||
|
||||
length := int64(toUint32(thisObject.get(propertyLength)))
|
||||
|
@ -253,7 +252,7 @@ func builtinArray_slice(call FunctionCall) Value {
|
|||
|
||||
if start >= end {
|
||||
// Always an empty array
|
||||
return toValue_object(call.runtime.newArray(0))
|
||||
return objectValue(call.runtime.newArray(0))
|
||||
}
|
||||
sliceLength := end - start
|
||||
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()
|
||||
length := int64(toUint32(thisObject.get(propertyLength)))
|
||||
itemList := call.ArgumentList
|
||||
|
@ -288,12 +287,12 @@ func builtinArray_unshift(call FunctionCall) Value {
|
|||
thisObject.put(arrayIndexToString(index), itemList[index], true)
|
||||
}
|
||||
|
||||
newLength := toValue_int64(length + itemCount)
|
||||
newLength := int64Value(length + itemCount)
|
||||
thisObject.put(propertyLength, newLength, true)
|
||||
return newLength
|
||||
}
|
||||
|
||||
func builtinArray_reverse(call FunctionCall) Value {
|
||||
func builtinArrayReverse(call FunctionCall) Value {
|
||||
thisObject := call.thisObject()
|
||||
length := int64(toUint32(thisObject.get(propertyLength)))
|
||||
|
||||
|
@ -315,30 +314,29 @@ func builtinArray_reverse(call FunctionCall) Value {
|
|||
lower.exists = thisObject.hasProperty(lower.name)
|
||||
upper.exists = thisObject.hasProperty(upper.name)
|
||||
|
||||
if lower.exists && upper.exists {
|
||||
switch {
|
||||
case lower.exists && upper.exists:
|
||||
lowerValue := thisObject.get(lower.name)
|
||||
upperValue := thisObject.get(upper.name)
|
||||
thisObject.put(lower.name, upperValue, true)
|
||||
thisObject.put(upper.name, lowerValue, true)
|
||||
} else if !lower.exists && upper.exists {
|
||||
case !lower.exists && upper.exists:
|
||||
value := thisObject.get(upper.name)
|
||||
thisObject.delete(upper.name, true)
|
||||
thisObject.put(lower.name, value, true)
|
||||
} else if lower.exists && !upper.exists {
|
||||
case lower.exists && !upper.exists:
|
||||
value := thisObject.get(lower.name)
|
||||
thisObject.delete(lower.name, true)
|
||||
thisObject.put(upper.name, value, true)
|
||||
} else {
|
||||
// Nothing happens.
|
||||
}
|
||||
|
||||
lower.index += 1
|
||||
lower.index++
|
||||
}
|
||||
|
||||
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 {
|
||||
name string
|
||||
exists bool
|
||||
|
@ -351,11 +349,12 @@ func sortCompare(thisObject *_object, index0, index1 uint, compare *_object) int
|
|||
k.name = arrayIndexToString(int64(index1))
|
||||
k.exists = thisObject.hasProperty(k.name)
|
||||
|
||||
if !j.exists && !k.exists {
|
||||
switch {
|
||||
case !j.exists && !k.exists:
|
||||
return 0
|
||||
} else if !j.exists {
|
||||
case !j.exists:
|
||||
return 1
|
||||
} else if !k.exists {
|
||||
case !k.exists:
|
||||
return -1
|
||||
}
|
||||
|
||||
|
@ -364,11 +363,12 @@ func sortCompare(thisObject *_object, index0, index1 uint, compare *_object) int
|
|||
j.defined = x.IsDefined()
|
||||
k.defined = y.IsDefined()
|
||||
|
||||
if !j.defined && !k.defined {
|
||||
switch {
|
||||
case !j.defined && !k.defined:
|
||||
return 0
|
||||
} else if !j.defined {
|
||||
case !j.defined:
|
||||
return 1
|
||||
} else if !k.defined {
|
||||
case !k.defined:
|
||||
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))
|
||||
}
|
||||
|
||||
func arraySortSwap(thisObject *_object, index0, index1 uint) {
|
||||
func arraySortSwap(thisObject *object, index0, index1 uint) {
|
||||
j := struct {
|
||||
name string
|
||||
exists bool
|
||||
|
@ -400,25 +400,24 @@ func arraySortSwap(thisObject *_object, index0, index1 uint) {
|
|||
k.name = arrayIndexToString(int64(index1))
|
||||
k.exists = thisObject.hasProperty(k.name)
|
||||
|
||||
if j.exists && k.exists {
|
||||
jValue := thisObject.get(j.name)
|
||||
kValue := thisObject.get(k.name)
|
||||
thisObject.put(j.name, kValue, true)
|
||||
thisObject.put(k.name, jValue, true)
|
||||
} else if !j.exists && k.exists {
|
||||
switch {
|
||||
case j.exists && k.exists:
|
||||
jv := thisObject.get(j.name)
|
||||
kv := thisObject.get(k.name)
|
||||
thisObject.put(j.name, kv, true)
|
||||
thisObject.put(k.name, jv, true)
|
||||
case !j.exists && k.exists:
|
||||
value := thisObject.get(k.name)
|
||||
thisObject.delete(k.name, true)
|
||||
thisObject.put(j.name, value, true)
|
||||
} else if j.exists && !k.exists {
|
||||
case j.exists && !k.exists:
|
||||
value := thisObject.get(j.name)
|
||||
thisObject.delete(j.name, 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
|
||||
cursor := left
|
||||
cursor2 := left
|
||||
|
@ -429,18 +428,18 @@ func arraySortQuickPartition(thisObject *_object, left, right, pivot uint, compa
|
|||
if cursor < cursor2 {
|
||||
arraySortSwap(thisObject, index, cursor2)
|
||||
}
|
||||
cursor += 1
|
||||
cursor2 += 1
|
||||
cursor++
|
||||
cursor2++
|
||||
} else if comparison == 0 {
|
||||
arraySortSwap(thisObject, index, cursor2)
|
||||
cursor2 += 1
|
||||
cursor2++
|
||||
}
|
||||
}
|
||||
arraySortSwap(thisObject, cursor2, right)
|
||||
return cursor, cursor2
|
||||
}
|
||||
|
||||
func arraySortQuickSort(thisObject *_object, left, right uint, compare *_object) {
|
||||
func arraySortQuickSort(thisObject *object, left, right uint, compare *object) {
|
||||
if left < right {
|
||||
middle := left + (right-left)/2
|
||||
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()
|
||||
length := uint(toUint32(thisObject.get(propertyLength)))
|
||||
compareValue := call.Argument(0)
|
||||
compare := compareValue._object()
|
||||
compare := compareValue.object()
|
||||
if compareValue.IsUndefined() {
|
||||
} else if !compareValue.isCallable() {
|
||||
panic(call.runtime.panicTypeError())
|
||||
panic(call.runtime.panicTypeError("Array.sort value %q is not callable", compareValue))
|
||||
}
|
||||
if length > 1 {
|
||||
arraySortQuickSort(thisObject, 0, length-1, compare)
|
||||
|
@ -466,11 +465,11 @@ func builtinArray_sort(call FunctionCall) Value {
|
|||
return call.This
|
||||
}
|
||||
|
||||
func builtinArray_isArray(call FunctionCall) Value {
|
||||
return toValue_bool(isArray(call.Argument(0)._object()))
|
||||
func builtinArrayIsArray(call FunctionCall) Value {
|
||||
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)
|
||||
if length := int64(toUint32(thisObject.get(propertyLength))); length > 0 {
|
||||
index := int64(0)
|
||||
|
@ -485,20 +484,20 @@ func builtinArray_indexOf(call FunctionCall) Value {
|
|||
index = -1
|
||||
}
|
||||
for ; index >= 0 && index < length; index++ {
|
||||
name := arrayIndexToString(int64(index))
|
||||
name := arrayIndexToString(index)
|
||||
if !thisObject.hasProperty(name) {
|
||||
continue
|
||||
}
|
||||
value := thisObject.get(name)
|
||||
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)
|
||||
length := int64(toUint32(thisObject.get(propertyLength)))
|
||||
index := length - 1
|
||||
|
@ -511,30 +510,30 @@ func builtinArray_lastIndexOf(call FunctionCall) Value {
|
|||
if index > length {
|
||||
index = length - 1
|
||||
} else if 0 > index {
|
||||
return toValue_int(-1)
|
||||
return intValue(-1)
|
||||
}
|
||||
for ; index >= 0; index-- {
|
||||
name := arrayIndexToString(int64(index))
|
||||
name := arrayIndexToString(index)
|
||||
if !thisObject.hasProperty(name) {
|
||||
continue
|
||||
}
|
||||
value := thisObject.get(name)
|
||||
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()
|
||||
this := toValue_object(thisObject)
|
||||
this := objectValue(thisObject)
|
||||
if iterator := call.Argument(0); iterator.isCallable() {
|
||||
length := int64(toUint32(thisObject.get(propertyLength)))
|
||||
callThis := call.Argument(1)
|
||||
for index := int64(0); index < length; index++ {
|
||||
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
|
||||
}
|
||||
return falseValue
|
||||
|
@ -542,46 +541,46 @@ func builtinArray_every(call FunctionCall) Value {
|
|||
}
|
||||
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()
|
||||
this := toValue_object(thisObject)
|
||||
this := objectValue(thisObject)
|
||||
if iterator := call.Argument(0); iterator.isCallable() {
|
||||
length := int64(toUint32(thisObject.get(propertyLength)))
|
||||
callThis := call.Argument(1)
|
||||
for index := int64(0); index < length; index++ {
|
||||
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 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()
|
||||
this := toValue_object(thisObject)
|
||||
this := objectValue(thisObject)
|
||||
if iterator := call.Argument(0); iterator.isCallable() {
|
||||
length := int64(toUint32(thisObject.get(propertyLength)))
|
||||
callThis := call.Argument(1)
|
||||
for index := int64(0); index < length; index++ {
|
||||
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{}
|
||||
}
|
||||
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()
|
||||
this := toValue_object(thisObject)
|
||||
this := objectValue(thisObject)
|
||||
if iterator := call.Argument(0); iterator.isCallable() {
|
||||
length := int64(toUint32(thisObject.get(propertyLength)))
|
||||
callThis := call.Argument(1)
|
||||
|
@ -593,14 +592,14 @@ func builtinArray_map(call FunctionCall) 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()
|
||||
this := toValue_object(thisObject)
|
||||
this := objectValue(thisObject)
|
||||
if iterator := call.Argument(0); iterator.isCallable() {
|
||||
length := int64(toUint32(thisObject.get(propertyLength)))
|
||||
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()
|
||||
this := toValue_object(thisObject)
|
||||
this := objectValue(thisObject)
|
||||
if iterator := call.Argument(0); iterator.isCallable() {
|
||||
initial := len(call.ArgumentList) > 1
|
||||
start := call.Argument(1)
|
||||
|
@ -633,6 +632,7 @@ func builtinArray_reduce(call FunctionCall) Value {
|
|||
if key := arrayIndexToString(index); thisObject.hasProperty(key) {
|
||||
accumulator = thisObject.get(key)
|
||||
index++
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
|
@ -647,12 +647,12 @@ func builtinArray_reduce(call FunctionCall) Value {
|
|||
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()
|
||||
this := toValue_object(thisObject)
|
||||
this := objectValue(thisObject)
|
||||
if iterator := call.Argument(0); iterator.isCallable() {
|
||||
initial := len(call.ArgumentList) > 1
|
||||
start := call.Argument(1)
|
||||
|
@ -679,5 +679,5 @@ func builtinArray_reduceRight(call FunctionCall) Value {
|
|||
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
|
||||
|
||||
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 {
|
||||
return toValue_object(self.runtime.newBoolean(valueOfArrayIndex(argumentList, 0)))
|
||||
func builtinNewBoolean(obj *object, argumentList []Value) Value {
|
||||
return objectValue(obj.runtime.newBoolean(valueOfArrayIndex(argumentList, 0)))
|
||||
}
|
||||
|
||||
func builtinBoolean_toString(call FunctionCall) Value {
|
||||
func builtinBooleanToString(call FunctionCall) Value {
|
||||
value := call.This
|
||||
if !value.IsBoolean() {
|
||||
// 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
|
||||
if !value.IsBoolean() {
|
||||
value = call.thisClassObject(classBoolean).primitiveValue()
|
||||
value = call.thisClassObject(classBooleanName).primitiveValue()
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
|
339
v1/vendor/github.com/robertkrimen/otto/builtin_date.go
generated
vendored
|
@ -2,121 +2,118 @@ package otto
|
|||
|
||||
import (
|
||||
"math"
|
||||
Time "time"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Date
|
||||
|
||||
const (
|
||||
// TODO Be like V8?
|
||||
// builtinDate_goDateTimeLayout = "Mon Jan 2 2006 15:04:05 GMT-0700 (MST)"
|
||||
builtinDate_goDateTimeLayout = Time.RFC1123 // "Mon, 02 Jan 2006 15:04:05 MST"
|
||||
builtinDate_goDateLayout = "Mon, 02 Jan 2006"
|
||||
builtinDate_goTimeLayout = "15:04:05 MST"
|
||||
// builtinDateDateTimeLayout = "Mon Jan 2 2006 15:04:05 GMT-0700 (MST)".
|
||||
builtinDateDateTimeLayout = time.RFC1123 // "Mon, 02 Jan 2006 15:04:05 MST"
|
||||
builtinDateDateLayout = "Mon, 02 Jan 2006"
|
||||
builtinDateTimeLayout = "15:04:05 MST"
|
||||
)
|
||||
|
||||
var (
|
||||
// utcTimeZone is the time zone used for UTC calculations.
|
||||
// It is GMT not UTC as that's what Javascript does because toUTCString is
|
||||
// actually an alias to toGMTString.
|
||||
utcTimeZone = Time.FixedZone("GMT", 0)
|
||||
)
|
||||
// utcTimeZone is the time zone used for UTC calculations.
|
||||
// It is GMT not UTC as that's what Javascript does because toUTCString is
|
||||
// actually an alias to toGMTString.
|
||||
var utcTimeZone = time.FixedZone("GMT", 0)
|
||||
|
||||
func builtinDate(call FunctionCall) Value {
|
||||
date := &_dateObject{}
|
||||
date.Set(newDateTime([]Value{}, Time.Local))
|
||||
return toValue_string(date.Time().Format(builtinDate_goDateTimeLayout))
|
||||
date := &dateObject{}
|
||||
date.Set(newDateTime([]Value{}, time.Local)) //nolint: gosmopolitan
|
||||
return stringValue(date.Time().Format(builtinDateDateTimeLayout))
|
||||
}
|
||||
|
||||
func builtinNewDate(self *_object, argumentList []Value) Value {
|
||||
return toValue_object(self.runtime.newDate(newDateTime(argumentList, Time.Local)))
|
||||
func builtinNewDate(obj *object, argumentList []Value) Value {
|
||||
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())
|
||||
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())
|
||||
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())
|
||||
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())
|
||||
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())
|
||||
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 {
|
||||
object := call.thisObject()
|
||||
value := object.DefaultValue(defaultValueHintNumber) // FIXME object.primitiveNumberValue
|
||||
{ // FIXME value.isFinite
|
||||
value := value.float64()
|
||||
if math.IsNaN(value) || math.IsInf(value, 0) {
|
||||
func builtinDateToJSON(call FunctionCall) Value {
|
||||
obj := call.thisObject()
|
||||
value := obj.DefaultValue(defaultValueHintNumber) // FIXME object.primitiveNumberValue
|
||||
// FIXME fv.isFinite
|
||||
if fv := value.float64(); math.IsNaN(fv) || math.IsInf(fv, 0) {
|
||||
return nullValue
|
||||
}
|
||||
}
|
||||
toISOString := object.get("toISOString")
|
||||
|
||||
toISOString := obj.get("toISOString")
|
||||
if !toISOString.isCallable() {
|
||||
// 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())
|
||||
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())
|
||||
if date.isNaN {
|
||||
return NaNValue()
|
||||
}
|
||||
// We do this (convert away from a float) so the user
|
||||
// does not get something back in exponential notation
|
||||
return toValue_int64(int64(date.Epoch()))
|
||||
return int64Value(date.Epoch())
|
||||
}
|
||||
|
||||
func builtinDate_setTime(call FunctionCall) Value {
|
||||
object := call.thisObject()
|
||||
func builtinDateSetTime(call FunctionCall) Value {
|
||||
obj := call.thisObject()
|
||||
date := dateObjectOf(call.runtime, call.thisObject())
|
||||
date.Set(call.Argument(0).float64())
|
||||
object.value = date
|
||||
obj.value = date
|
||||
return date.Value()
|
||||
}
|
||||
|
||||
func _builtinDate_beforeSet(call FunctionCall, argumentLimit int, timeLocal bool) (*_object, *_dateObject, *_ecmaTime, []int) {
|
||||
object := call.thisObject()
|
||||
func builtinDateBeforeSet(call FunctionCall, argumentLimit int, timeLocal bool) (*object, *dateObject, *ecmaTime, []int) {
|
||||
obj := call.thisObject()
|
||||
date := dateObjectOf(call.runtime, call.thisObject())
|
||||
if date.isNaN {
|
||||
return nil, nil, nil, nil
|
||||
|
@ -127,7 +124,7 @@ func _builtinDate_beforeSet(call FunctionCall, argumentLimit int, timeLocal bool
|
|||
}
|
||||
|
||||
if argumentLimit == 0 {
|
||||
object.value = invalidDateObject
|
||||
obj.value = invalidDateObject
|
||||
return nil, nil, nil, nil
|
||||
}
|
||||
|
||||
|
@ -138,61 +135,61 @@ func _builtinDate_beforeSet(call FunctionCall, argumentLimit int, timeLocal bool
|
|||
switch nm.kind {
|
||||
case numberInteger, numberFloat:
|
||||
default:
|
||||
object.value = invalidDateObject
|
||||
obj.value = invalidDateObject
|
||||
return nil, nil, nil, nil
|
||||
}
|
||||
valueList[index] = int(nm.int64)
|
||||
}
|
||||
baseTime := date.Time()
|
||||
if timeLocal {
|
||||
baseTime = baseTime.Local()
|
||||
baseTime = baseTime.Local() //nolint: gosmopolitan
|
||||
}
|
||||
ecmaTime := ecmaTime(baseTime)
|
||||
return object, &date, &ecmaTime, valueList
|
||||
ecmaTime := newEcmaTime(baseTime)
|
||||
return obj, &date, &ecmaTime, valueList
|
||||
}
|
||||
|
||||
func builtinDate_parse(call FunctionCall) Value {
|
||||
func builtinDateParse(call FunctionCall) Value {
|
||||
date := call.Argument(0).string()
|
||||
return toValue_float64(dateParse(date))
|
||||
return float64Value(dateParse(date))
|
||||
}
|
||||
|
||||
func builtinDate_UTC(call FunctionCall) Value {
|
||||
return toValue_float64(newDateTime(call.ArgumentList, Time.UTC))
|
||||
func builtinDateUTC(call FunctionCall) Value {
|
||||
return float64Value(newDateTime(call.ArgumentList, time.UTC))
|
||||
}
|
||||
|
||||
func builtinDate_now(call FunctionCall) Value {
|
||||
func builtinDateNow(call FunctionCall) Value {
|
||||
call.ArgumentList = []Value(nil)
|
||||
return builtinDate_UTC(call)
|
||||
return builtinDateUTC(call)
|
||||
}
|
||||
|
||||
// This is a placeholder
|
||||
func builtinDate_toLocaleString(call FunctionCall) Value {
|
||||
// This is a placeholder.
|
||||
func builtinDateToLocaleString(call FunctionCall) Value {
|
||||
date := dateObjectOf(call.runtime, call.thisObject())
|
||||
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
|
||||
func builtinDate_toLocaleDateString(call FunctionCall) Value {
|
||||
// This is a placeholder.
|
||||
func builtinDateToLocaleDateString(call FunctionCall) Value {
|
||||
date := dateObjectOf(call.runtime, call.thisObject())
|
||||
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
|
||||
func builtinDate_toLocaleTimeString(call FunctionCall) Value {
|
||||
// This is a placeholder.
|
||||
func builtinDateToLocaleTimeString(call FunctionCall) Value {
|
||||
date := dateObjectOf(call.runtime, call.thisObject())
|
||||
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())
|
||||
if date.isNaN {
|
||||
return NaNValue()
|
||||
|
@ -200,155 +197,155 @@ func builtinDate_valueOf(call FunctionCall) Value {
|
|||
return date.Value()
|
||||
}
|
||||
|
||||
func builtinDate_getYear(call FunctionCall) Value {
|
||||
func builtinDateGetYear(call FunctionCall) Value {
|
||||
// Will throw a TypeError is ThisObject is nil or
|
||||
// does not have Class of "Date"
|
||||
date := dateObjectOf(call.runtime, call.thisObject())
|
||||
if date.isNaN {
|
||||
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
|
||||
// does not have Class of "Date"
|
||||
date := dateObjectOf(call.runtime, call.thisObject())
|
||||
if date.isNaN {
|
||||
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())
|
||||
if date.isNaN {
|
||||
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())
|
||||
if date.isNaN {
|
||||
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())
|
||||
if date.isNaN {
|
||||
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())
|
||||
if date.isNaN {
|
||||
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())
|
||||
if date.isNaN {
|
||||
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
|
||||
date := dateObjectOf(call.runtime, call.thisObject())
|
||||
if date.isNaN {
|
||||
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())
|
||||
if date.isNaN {
|
||||
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())
|
||||
if date.isNaN {
|
||||
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())
|
||||
if date.isNaN {
|
||||
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())
|
||||
if date.isNaN {
|
||||
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())
|
||||
if date.isNaN {
|
||||
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())
|
||||
if date.isNaN {
|
||||
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())
|
||||
if date.isNaN {
|
||||
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())
|
||||
if date.isNaN {
|
||||
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())
|
||||
if date.isNaN {
|
||||
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())
|
||||
if date.isNaN {
|
||||
return NaNValue()
|
||||
}
|
||||
timeLocal := date.Time().Local()
|
||||
timeLocal := date.Time().Local() //nolint: gosmopolitan
|
||||
// Is this kosher?
|
||||
timeLocalAsUTC := Time.Date(
|
||||
timeLocalAsUTC := time.Date(
|
||||
timeLocal.Year(),
|
||||
timeLocal.Month(),
|
||||
timeLocal.Day(),
|
||||
|
@ -356,13 +353,13 @@ func builtinDate_getTimezoneOffset(call FunctionCall) Value {
|
|||
timeLocal.Minute(),
|
||||
timeLocal.Second(),
|
||||
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 {
|
||||
object, date, ecmaTime, value := _builtinDate_beforeSet(call, 1, true)
|
||||
func builtinDateSetMilliseconds(call FunctionCall) Value {
|
||||
obj, date, ecmaTime, value := builtinDateBeforeSet(call, 1, true)
|
||||
if ecmaTime == nil {
|
||||
return NaNValue()
|
||||
}
|
||||
|
@ -370,12 +367,12 @@ func builtinDate_setMilliseconds(call FunctionCall) Value {
|
|||
ecmaTime.millisecond = value[0]
|
||||
|
||||
date.SetTime(ecmaTime.goTime())
|
||||
object.value = *date
|
||||
obj.value = *date
|
||||
return date.Value()
|
||||
}
|
||||
|
||||
func builtinDate_setUTCMilliseconds(call FunctionCall) Value {
|
||||
object, date, ecmaTime, value := _builtinDate_beforeSet(call, 1, false)
|
||||
func builtinDateSetUTCMilliseconds(call FunctionCall) Value {
|
||||
obj, date, ecmaTime, value := builtinDateBeforeSet(call, 1, false)
|
||||
if ecmaTime == nil {
|
||||
return NaNValue()
|
||||
}
|
||||
|
@ -383,12 +380,12 @@ func builtinDate_setUTCMilliseconds(call FunctionCall) Value {
|
|||
ecmaTime.millisecond = value[0]
|
||||
|
||||
date.SetTime(ecmaTime.goTime())
|
||||
object.value = *date
|
||||
obj.value = *date
|
||||
return date.Value()
|
||||
}
|
||||
|
||||
func builtinDate_setSeconds(call FunctionCall) Value {
|
||||
object, date, ecmaTime, value := _builtinDate_beforeSet(call, 2, true)
|
||||
func builtinDateSetSeconds(call FunctionCall) Value {
|
||||
obj, date, ecmaTime, value := builtinDateBeforeSet(call, 2, true)
|
||||
if ecmaTime == nil {
|
||||
return NaNValue()
|
||||
}
|
||||
|
@ -399,12 +396,12 @@ func builtinDate_setSeconds(call FunctionCall) Value {
|
|||
ecmaTime.second = value[0]
|
||||
|
||||
date.SetTime(ecmaTime.goTime())
|
||||
object.value = *date
|
||||
obj.value = *date
|
||||
return date.Value()
|
||||
}
|
||||
|
||||
func builtinDate_setUTCSeconds(call FunctionCall) Value {
|
||||
object, date, ecmaTime, value := _builtinDate_beforeSet(call, 2, false)
|
||||
func builtinDateSetUTCSeconds(call FunctionCall) Value {
|
||||
obj, date, ecmaTime, value := builtinDateBeforeSet(call, 2, false)
|
||||
if ecmaTime == nil {
|
||||
return NaNValue()
|
||||
}
|
||||
|
@ -415,12 +412,12 @@ func builtinDate_setUTCSeconds(call FunctionCall) Value {
|
|||
ecmaTime.second = value[0]
|
||||
|
||||
date.SetTime(ecmaTime.goTime())
|
||||
object.value = *date
|
||||
obj.value = *date
|
||||
return date.Value()
|
||||
}
|
||||
|
||||
func builtinDate_setMinutes(call FunctionCall) Value {
|
||||
object, date, ecmaTime, value := _builtinDate_beforeSet(call, 3, true)
|
||||
func builtinDateSetMinutes(call FunctionCall) Value {
|
||||
obj, date, ecmaTime, value := builtinDateBeforeSet(call, 3, true)
|
||||
if ecmaTime == nil {
|
||||
return NaNValue()
|
||||
}
|
||||
|
@ -434,12 +431,12 @@ func builtinDate_setMinutes(call FunctionCall) Value {
|
|||
ecmaTime.minute = value[0]
|
||||
|
||||
date.SetTime(ecmaTime.goTime())
|
||||
object.value = *date
|
||||
obj.value = *date
|
||||
return date.Value()
|
||||
}
|
||||
|
||||
func builtinDate_setUTCMinutes(call FunctionCall) Value {
|
||||
object, date, ecmaTime, value := _builtinDate_beforeSet(call, 3, false)
|
||||
func builtinDateSetUTCMinutes(call FunctionCall) Value {
|
||||
obj, date, ecmaTime, value := builtinDateBeforeSet(call, 3, false)
|
||||
if ecmaTime == nil {
|
||||
return NaNValue()
|
||||
}
|
||||
|
@ -453,58 +450,58 @@ func builtinDate_setUTCMinutes(call FunctionCall) Value {
|
|||
ecmaTime.minute = value[0]
|
||||
|
||||
date.SetTime(ecmaTime.goTime())
|
||||
object.value = *date
|
||||
obj.value = *date
|
||||
return date.Value()
|
||||
}
|
||||
|
||||
func builtinDate_setHours(call FunctionCall) Value {
|
||||
object, date, ecmaTime, value := _builtinDate_beforeSet(call, 4, true)
|
||||
func builtinDateSetHours(call FunctionCall) Value {
|
||||
obj, date, ecmaTime, value := builtinDateBeforeSet(call, 4, true)
|
||||
if ecmaTime == nil {
|
||||
return NaNValue()
|
||||
}
|
||||
|
||||
if len(value) > 3 {
|
||||
switch {
|
||||
case len(value) > 3:
|
||||
ecmaTime.millisecond = value[3]
|
||||
fallthrough
|
||||
case len(value) > 2:
|
||||
ecmaTime.second = value[2]
|
||||
ecmaTime.minute = value[1]
|
||||
} else if len(value) > 2 {
|
||||
ecmaTime.second = value[2]
|
||||
ecmaTime.minute = value[1]
|
||||
} else if len(value) > 1 {
|
||||
fallthrough
|
||||
case len(value) > 1:
|
||||
ecmaTime.minute = value[1]
|
||||
}
|
||||
ecmaTime.hour = value[0]
|
||||
|
||||
date.SetTime(ecmaTime.goTime())
|
||||
object.value = *date
|
||||
obj.value = *date
|
||||
return date.Value()
|
||||
}
|
||||
|
||||
func builtinDate_setUTCHours(call FunctionCall) Value {
|
||||
object, date, ecmaTime, value := _builtinDate_beforeSet(call, 4, false)
|
||||
func builtinDateSetUTCHours(call FunctionCall) Value {
|
||||
obj, date, ecmaTime, value := builtinDateBeforeSet(call, 4, false)
|
||||
if ecmaTime == nil {
|
||||
return NaNValue()
|
||||
}
|
||||
|
||||
if len(value) > 3 {
|
||||
switch {
|
||||
case len(value) > 3:
|
||||
ecmaTime.millisecond = value[3]
|
||||
fallthrough
|
||||
case len(value) > 2:
|
||||
ecmaTime.second = value[2]
|
||||
ecmaTime.minute = value[1]
|
||||
} else if len(value) > 2 {
|
||||
ecmaTime.second = value[2]
|
||||
ecmaTime.minute = value[1]
|
||||
} else if len(value) > 1 {
|
||||
fallthrough
|
||||
case len(value) > 1:
|
||||
ecmaTime.minute = value[1]
|
||||
}
|
||||
ecmaTime.hour = value[0]
|
||||
|
||||
date.SetTime(ecmaTime.goTime())
|
||||
object.value = *date
|
||||
obj.value = *date
|
||||
return date.Value()
|
||||
}
|
||||
|
||||
func builtinDate_setDate(call FunctionCall) Value {
|
||||
object, date, ecmaTime, value := _builtinDate_beforeSet(call, 1, true)
|
||||
func builtinDateSetDate(call FunctionCall) Value {
|
||||
obj, date, ecmaTime, value := builtinDateBeforeSet(call, 1, true)
|
||||
if ecmaTime == nil {
|
||||
return NaNValue()
|
||||
}
|
||||
|
@ -512,12 +509,12 @@ func builtinDate_setDate(call FunctionCall) Value {
|
|||
ecmaTime.day = value[0]
|
||||
|
||||
date.SetTime(ecmaTime.goTime())
|
||||
object.value = *date
|
||||
obj.value = *date
|
||||
return date.Value()
|
||||
}
|
||||
|
||||
func builtinDate_setUTCDate(call FunctionCall) Value {
|
||||
object, date, ecmaTime, value := _builtinDate_beforeSet(call, 1, false)
|
||||
func builtinDateSetUTCDate(call FunctionCall) Value {
|
||||
obj, date, ecmaTime, value := builtinDateBeforeSet(call, 1, false)
|
||||
if ecmaTime == nil {
|
||||
return NaNValue()
|
||||
}
|
||||
|
@ -525,12 +522,12 @@ func builtinDate_setUTCDate(call FunctionCall) Value {
|
|||
ecmaTime.day = value[0]
|
||||
|
||||
date.SetTime(ecmaTime.goTime())
|
||||
object.value = *date
|
||||
obj.value = *date
|
||||
return date.Value()
|
||||
}
|
||||
|
||||
func builtinDate_setMonth(call FunctionCall) Value {
|
||||
object, date, ecmaTime, value := _builtinDate_beforeSet(call, 2, true)
|
||||
func builtinDateSetMonth(call FunctionCall) Value {
|
||||
obj, date, ecmaTime, value := builtinDateBeforeSet(call, 2, true)
|
||||
if ecmaTime == nil {
|
||||
return NaNValue()
|
||||
}
|
||||
|
@ -541,12 +538,12 @@ func builtinDate_setMonth(call FunctionCall) Value {
|
|||
ecmaTime.month = value[0]
|
||||
|
||||
date.SetTime(ecmaTime.goTime())
|
||||
object.value = *date
|
||||
obj.value = *date
|
||||
return date.Value()
|
||||
}
|
||||
|
||||
func builtinDate_setUTCMonth(call FunctionCall) Value {
|
||||
object, date, ecmaTime, value := _builtinDate_beforeSet(call, 2, false)
|
||||
func builtinDateSetUTCMonth(call FunctionCall) Value {
|
||||
obj, date, ecmaTime, value := builtinDateBeforeSet(call, 2, false)
|
||||
if ecmaTime == nil {
|
||||
return NaNValue()
|
||||
}
|
||||
|
@ -557,12 +554,12 @@ func builtinDate_setUTCMonth(call FunctionCall) Value {
|
|||
ecmaTime.month = value[0]
|
||||
|
||||
date.SetTime(ecmaTime.goTime())
|
||||
object.value = *date
|
||||
obj.value = *date
|
||||
return date.Value()
|
||||
}
|
||||
|
||||
func builtinDate_setYear(call FunctionCall) Value {
|
||||
object, date, ecmaTime, value := _builtinDate_beforeSet(call, 1, true)
|
||||
func builtinDateSetYear(call FunctionCall) Value {
|
||||
obj, date, ecmaTime, value := builtinDateBeforeSet(call, 1, true)
|
||||
if ecmaTime == nil {
|
||||
return NaNValue()
|
||||
}
|
||||
|
@ -574,12 +571,12 @@ func builtinDate_setYear(call FunctionCall) Value {
|
|||
ecmaTime.year = year
|
||||
|
||||
date.SetTime(ecmaTime.goTime())
|
||||
object.value = *date
|
||||
obj.value = *date
|
||||
return date.Value()
|
||||
}
|
||||
|
||||
func builtinDate_setFullYear(call FunctionCall) Value {
|
||||
object, date, ecmaTime, value := _builtinDate_beforeSet(call, 3, true)
|
||||
func builtinDateSetFullYear(call FunctionCall) Value {
|
||||
obj, date, ecmaTime, value := builtinDateBeforeSet(call, 3, true)
|
||||
if ecmaTime == nil {
|
||||
return NaNValue()
|
||||
}
|
||||
|
@ -593,12 +590,12 @@ func builtinDate_setFullYear(call FunctionCall) Value {
|
|||
ecmaTime.year = value[0]
|
||||
|
||||
date.SetTime(ecmaTime.goTime())
|
||||
object.value = *date
|
||||
obj.value = *date
|
||||
return date.Value()
|
||||
}
|
||||
|
||||
func builtinDate_setUTCFullYear(call FunctionCall) Value {
|
||||
object, date, ecmaTime, value := _builtinDate_beforeSet(call, 3, false)
|
||||
func builtinDateSetUTCFullYear(call FunctionCall) Value {
|
||||
obj, date, ecmaTime, value := builtinDateBeforeSet(call, 3, false)
|
||||
if ecmaTime == nil {
|
||||
return NaNValue()
|
||||
}
|
||||
|
@ -612,7 +609,7 @@ func builtinDate_setUTCFullYear(call FunctionCall) Value {
|
|||
ecmaTime.year = value[0]
|
||||
|
||||
date.SetTime(ecmaTime.goTime())
|
||||
object.value = *date
|
||||
obj.value = *date
|
||||
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 {
|
||||
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 {
|
||||
return toValue_object(self.runtime.newError(classError, valueOfArrayIndex(argumentList, 0), 0))
|
||||
func builtinNewError(obj *object, argumentList []Value) Value {
|
||||
return objectValue(obj.runtime.newError(classErrorName, valueOfArrayIndex(argumentList, 0), 0))
|
||||
}
|
||||
|
||||
func builtinError_toString(call FunctionCall) Value {
|
||||
func builtinErrorToString(call FunctionCall) Value {
|
||||
thisObject := call.thisObject()
|
||||
if thisObject == nil {
|
||||
panic(call.runtime.panicTypeError())
|
||||
panic(call.runtime.panicTypeError("Error.toString is nil"))
|
||||
}
|
||||
|
||||
name := classError
|
||||
name := classErrorName
|
||||
nameValue := thisObject.get("name")
|
||||
if nameValue.IsDefined() {
|
||||
name = nameValue.string()
|
||||
|
@ -31,96 +31,96 @@ func builtinError_toString(call FunctionCall) Value {
|
|||
}
|
||||
|
||||
if len(name) == 0 {
|
||||
return toValue_string(message)
|
||||
return stringValue(message)
|
||||
}
|
||||
|
||||
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 {
|
||||
self := runtime.newErrorObject("EvalError", message, 0)
|
||||
self.prototype = runtime.global.EvalErrorPrototype
|
||||
return self
|
||||
func (rt *runtime) newEvalError(message Value) *object {
|
||||
o := rt.newErrorObject("EvalError", message, 0)
|
||||
o.prototype = rt.global.EvalErrorPrototype
|
||||
return o
|
||||
}
|
||||
|
||||
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 {
|
||||
return toValue_object(self.runtime.newEvalError(valueOfArrayIndex(argumentList, 0)))
|
||||
func builtinNewEvalError(obj *object, argumentList []Value) Value {
|
||||
return objectValue(obj.runtime.newEvalError(valueOfArrayIndex(argumentList, 0)))
|
||||
}
|
||||
|
||||
func (runtime *_runtime) newTypeError(message Value) *_object {
|
||||
self := runtime.newErrorObject("TypeError", message, 0)
|
||||
self.prototype = runtime.global.TypeErrorPrototype
|
||||
return self
|
||||
func (rt *runtime) newTypeError(message Value) *object {
|
||||
o := rt.newErrorObject("TypeError", message, 0)
|
||||
o.prototype = rt.global.TypeErrorPrototype
|
||||
return o
|
||||
}
|
||||
|
||||
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 {
|
||||
return toValue_object(self.runtime.newTypeError(valueOfArrayIndex(argumentList, 0)))
|
||||
func builtinNewTypeError(obj *object, argumentList []Value) Value {
|
||||
return objectValue(obj.runtime.newTypeError(valueOfArrayIndex(argumentList, 0)))
|
||||
}
|
||||
|
||||
func (runtime *_runtime) newRangeError(message Value) *_object {
|
||||
self := runtime.newErrorObject("RangeError", message, 0)
|
||||
self.prototype = runtime.global.RangeErrorPrototype
|
||||
return self
|
||||
func (rt *runtime) newRangeError(message Value) *object {
|
||||
o := rt.newErrorObject("RangeError", message, 0)
|
||||
o.prototype = rt.global.RangeErrorPrototype
|
||||
return o
|
||||
}
|
||||
|
||||
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 {
|
||||
return toValue_object(self.runtime.newRangeError(valueOfArrayIndex(argumentList, 0)))
|
||||
func builtinNewRangeError(obj *object, argumentList []Value) Value {
|
||||
return objectValue(obj.runtime.newRangeError(valueOfArrayIndex(argumentList, 0)))
|
||||
}
|
||||
|
||||
func (runtime *_runtime) newURIError(message Value) *_object {
|
||||
self := runtime.newErrorObject("URIError", message, 0)
|
||||
self.prototype = runtime.global.URIErrorPrototype
|
||||
return self
|
||||
func (rt *runtime) newURIError(message Value) *object {
|
||||
o := rt.newErrorObject("URIError", message, 0)
|
||||
o.prototype = rt.global.URIErrorPrototype
|
||||
return o
|
||||
}
|
||||
|
||||
func (runtime *_runtime) newReferenceError(message Value) *_object {
|
||||
self := runtime.newErrorObject("ReferenceError", message, 0)
|
||||
self.prototype = runtime.global.ReferenceErrorPrototype
|
||||
return self
|
||||
func (rt *runtime) newReferenceError(message Value) *object {
|
||||
o := rt.newErrorObject("ReferenceError", message, 0)
|
||||
o.prototype = rt.global.ReferenceErrorPrototype
|
||||
return o
|
||||
}
|
||||
|
||||
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 {
|
||||
return toValue_object(self.runtime.newReferenceError(valueOfArrayIndex(argumentList, 0)))
|
||||
func builtinNewReferenceError(obj *object, argumentList []Value) Value {
|
||||
return objectValue(obj.runtime.newReferenceError(valueOfArrayIndex(argumentList, 0)))
|
||||
}
|
||||
|
||||
func (runtime *_runtime) newSyntaxError(message Value) *_object {
|
||||
self := runtime.newErrorObject("SyntaxError", message, 0)
|
||||
self.prototype = runtime.global.SyntaxErrorPrototype
|
||||
return self
|
||||
func (rt *runtime) newSyntaxError(message Value) *object {
|
||||
o := rt.newErrorObject("SyntaxError", message, 0)
|
||||
o.prototype = rt.global.SyntaxErrorPrototype
|
||||
return o
|
||||
}
|
||||
|
||||
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 {
|
||||
return toValue_object(self.runtime.newSyntaxError(valueOfArrayIndex(argumentList, 0)))
|
||||
func builtinNewSyntaxError(obj *object, argumentList []Value) Value {
|
||||
return objectValue(obj.runtime.newSyntaxError(valueOfArrayIndex(argumentList, 0)))
|
||||
}
|
||||
|
||||
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 {
|
||||
return toValue_object(self.runtime.newURIError(valueOfArrayIndex(argumentList, 0)))
|
||||
func builtinNewURIError(obj *object, argumentList []Value) Value {
|
||||
return objectValue(obj.runtime.newURIError(valueOfArrayIndex(argumentList, 0)))
|
||||
}
|
||||
|
|
67
v1/vendor/github.com/robertkrimen/otto/builtin_function.go
generated
vendored
|
@ -11,11 +11,11 @@ import (
|
|||
// Function
|
||||
|
||||
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 {
|
||||
return toValue_object(builtinNewFunctionNative(self.runtime, argumentList))
|
||||
func builtinNewFunction(obj *object, argumentList []Value) Value {
|
||||
return objectValue(builtinNewFunctionNative(obj.runtime, argumentList))
|
||||
}
|
||||
|
||||
func argumentList2parameterList(argumentList []Value) []string {
|
||||
|
@ -29,10 +29,9 @@ func argumentList2parameterList(argumentList []Value) []string {
|
|||
return parameterList
|
||||
}
|
||||
|
||||
func builtinNewFunctionNative(runtime *_runtime, argumentList []Value) *_object {
|
||||
func builtinNewFunctionNative(rt *runtime, argumentList []Value) *object {
|
||||
var parameterList, body string
|
||||
count := len(argumentList)
|
||||
if count > 0 {
|
||||
if count := len(argumentList); count > 0 {
|
||||
tmp := make([]string, 0, count-1)
|
||||
for _, value := range argumentList[0 : count-1] {
|
||||
tmp = append(tmp, value.string())
|
||||
|
@ -43,35 +42,35 @@ func builtinNewFunctionNative(runtime *_runtime, argumentList []Value) *_object
|
|||
|
||||
// FIXME
|
||||
function, err := parser.ParseFunction(parameterList, body)
|
||||
runtime.parseThrow(err) // Will panic/throw appropriately
|
||||
cmpl := _compiler{}
|
||||
cmpl_function := cmpl.parseExpression(function)
|
||||
rt.parseThrow(err) // Will panic/throw appropriately
|
||||
cmpl := compiler{}
|
||||
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 {
|
||||
object := call.thisClassObject(classFunction) // Should throw a TypeError unless Function
|
||||
switch fn := object.value.(type) {
|
||||
case _nativeFunctionObject:
|
||||
return toValue_string(fmt.Sprintf("function %s() { [native code] }", fn.name))
|
||||
case _nodeFunctionObject:
|
||||
return toValue_string(fn.node.source)
|
||||
case _bindFunctionObject:
|
||||
return toValue_string("function () { [native code] }")
|
||||
func builtinFunctionToString(call FunctionCall) Value {
|
||||
obj := call.thisClassObject(classFunctionName) // Should throw a TypeError unless Function
|
||||
switch fn := obj.value.(type) {
|
||||
case nativeFunctionObject:
|
||||
return stringValue(fmt.Sprintf("function %s() { [native code] }", fn.name))
|
||||
case nodeFunctionObject:
|
||||
return stringValue(fn.node.source)
|
||||
case bindFunctionObject:
|
||||
return stringValue("function () { [native code] }")
|
||||
default:
|
||||
panic(call.runtime.panicTypeError("Function.toString unknown type %T", obj.value))
|
||||
}
|
||||
|
||||
panic(call.runtime.panicTypeError("Function.toString()"))
|
||||
}
|
||||
|
||||
func builtinFunction_apply(call FunctionCall) Value {
|
||||
func builtinFunctionApply(call FunctionCall) Value {
|
||||
if !call.This.isCallable() {
|
||||
panic(call.runtime.panicTypeError())
|
||||
panic(call.runtime.panicTypeError("Function.apply %q is not callable", call.This))
|
||||
}
|
||||
this := call.Argument(0)
|
||||
if this.IsUndefined() {
|
||||
// FIXME Not ECMA5
|
||||
this = toValue_object(call.runtime.globalObject)
|
||||
this = objectValue(call.runtime.globalObject)
|
||||
}
|
||||
argumentList := call.Argument(1)
|
||||
switch argumentList.kind {
|
||||
|
@ -79,10 +78,10 @@ func builtinFunction_apply(call FunctionCall) Value {
|
|||
return call.thisObject().call(this, nil, false, nativeFrame)
|
||||
case valueObject:
|
||||
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()
|
||||
length := int64(toUint32(arrayObject.get(propertyLength)))
|
||||
valueArray := make([]Value, length)
|
||||
|
@ -92,15 +91,15 @@ func builtinFunction_apply(call FunctionCall) Value {
|
|||
return thisObject.call(this, valueArray, false, nativeFrame)
|
||||
}
|
||||
|
||||
func builtinFunction_call(call FunctionCall) Value {
|
||||
func builtinFunctionCall(call FunctionCall) Value {
|
||||
if !call.This.isCallable() {
|
||||
panic(call.runtime.panicTypeError())
|
||||
panic(call.runtime.panicTypeError("Function.call %q is not callable", call.This))
|
||||
}
|
||||
thisObject := call.thisObject()
|
||||
this := call.Argument(0)
|
||||
if this.IsUndefined() {
|
||||
// FIXME Not ECMA5
|
||||
this = toValue_object(call.runtime.globalObject)
|
||||
this = objectValue(call.runtime.globalObject)
|
||||
}
|
||||
if len(call.ArgumentList) >= 1 {
|
||||
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)
|
||||
}
|
||||
|
||||
func builtinFunction_bind(call FunctionCall) Value {
|
||||
func builtinFunctionBind(call FunctionCall) Value {
|
||||
target := call.This
|
||||
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)
|
||||
argumentList := call.slice(1)
|
||||
if this.IsUndefined() {
|
||||
// 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"
|
||||
)
|
||||
|
||||
type _builtinJSON_parseContext struct {
|
||||
type builtinJSONParseContext struct {
|
||||
call FunctionCall
|
||||
reviver Value
|
||||
}
|
||||
|
||||
func builtinJSON_parse(call FunctionCall) Value {
|
||||
ctx := _builtinJSON_parseContext{
|
||||
func builtinJSONParse(call FunctionCall) Value {
|
||||
ctx := builtinJSONParseContext{
|
||||
call: call,
|
||||
}
|
||||
revive := false
|
||||
|
@ -27,109 +27,107 @@ func builtinJSON_parse(call FunctionCall) Value {
|
|||
if err != nil {
|
||||
panic(call.runtime.panicSyntaxError(err.Error()))
|
||||
}
|
||||
value, exists := builtinJSON_parseWalk(ctx, root)
|
||||
value, exists := builtinJSONParseWalk(ctx, root)
|
||||
if !exists {
|
||||
value = Value{}
|
||||
}
|
||||
if revive {
|
||||
root := ctx.call.runtime.newObject()
|
||||
root.put("", value, false)
|
||||
return builtinJSON_reviveWalk(ctx, root, "")
|
||||
return builtinJSONReviveWalk(ctx, root, "")
|
||||
}
|
||||
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)
|
||||
if object := value._object(); object != nil {
|
||||
if isArray(object) {
|
||||
length := int64(objectLength(object))
|
||||
for index := int64(0); index < length; index += 1 {
|
||||
if obj := value.object(); obj != nil {
|
||||
if isArray(obj) {
|
||||
length := int64(objectLength(obj))
|
||||
for index := int64(0); index < length; index++ {
|
||||
name := arrayIndexToString(index)
|
||||
value := builtinJSON_reviveWalk(ctx, object, name)
|
||||
value := builtinJSONReviveWalk(ctx, obj, name)
|
||||
if value.IsUndefined() {
|
||||
object.delete(name, false)
|
||||
obj.delete(name, false)
|
||||
} else {
|
||||
object.defineProperty(name, value, 0111, false)
|
||||
obj.defineProperty(name, value, 0o111, false)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
object.enumerate(false, func(name string) bool {
|
||||
value := builtinJSON_reviveWalk(ctx, object, name)
|
||||
obj.enumerate(false, func(name string) bool {
|
||||
value := builtinJSONReviveWalk(ctx, obj, name)
|
||||
if value.IsUndefined() {
|
||||
object.delete(name, false)
|
||||
obj.delete(name, false)
|
||||
} else {
|
||||
object.defineProperty(name, value, 0111, false)
|
||||
obj.defineProperty(name, value, 0o111, false)
|
||||
}
|
||||
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) {
|
||||
case nil:
|
||||
return nullValue, true
|
||||
case bool:
|
||||
return toValue_bool(value), true
|
||||
return boolValue(value), true
|
||||
case string:
|
||||
return toValue_string(value), true
|
||||
return stringValue(value), true
|
||||
case float64:
|
||||
return toValue_float64(value), true
|
||||
return float64Value(value), true
|
||||
case []interface{}:
|
||||
arrayValue := make([]Value, len(value))
|
||||
for index, rawValue := range value {
|
||||
if value, exists := builtinJSON_parseWalk(ctx, rawValue); exists {
|
||||
if value, exists := builtinJSONParseWalk(ctx, rawValue); exists {
|
||||
arrayValue[index] = value
|
||||
}
|
||||
}
|
||||
return toValue_object(ctx.call.runtime.newArrayOf(arrayValue)), true
|
||||
return objectValue(ctx.call.runtime.newArrayOf(arrayValue)), true
|
||||
case map[string]interface{}:
|
||||
object := ctx.call.runtime.newObject()
|
||||
obj := ctx.call.runtime.newObject()
|
||||
for name, rawValue := range value {
|
||||
if value, exists := builtinJSON_parseWalk(ctx, rawValue); exists {
|
||||
object.put(name, value, false)
|
||||
if value, exists := builtinJSONParseWalk(ctx, rawValue); exists {
|
||||
obj.put(name, value, false)
|
||||
}
|
||||
}
|
||||
return toValue_object(object), true
|
||||
return objectValue(obj), true
|
||||
}
|
||||
return Value{}, false
|
||||
}
|
||||
|
||||
type _builtinJSON_stringifyContext struct {
|
||||
type builtinJSONStringifyContext struct {
|
||||
call FunctionCall
|
||||
stack []*_object
|
||||
stack []*object
|
||||
propertyList []string
|
||||
replacerFunction *Value
|
||||
gap string
|
||||
}
|
||||
|
||||
func builtinJSON_stringify(call FunctionCall) Value {
|
||||
ctx := _builtinJSON_stringifyContext{
|
||||
func builtinJSONStringify(call FunctionCall) Value {
|
||||
ctx := builtinJSONStringifyContext{
|
||||
call: call,
|
||||
stack: []*_object{nil},
|
||||
stack: []*object{nil},
|
||||
}
|
||||
replacer := call.Argument(1)._object()
|
||||
replacer := call.Argument(1).object()
|
||||
if replacer != nil {
|
||||
if isArray(replacer) {
|
||||
length := objectLength(replacer)
|
||||
seen := map[string]bool{}
|
||||
propertyList := make([]string, length)
|
||||
length = 0
|
||||
for index, _ := range propertyList {
|
||||
for index := range propertyList {
|
||||
value := replacer.get(arrayIndexToString(int64(index)))
|
||||
switch value.kind {
|
||||
case valueObject:
|
||||
switch value.value.(*_object).class {
|
||||
case classString:
|
||||
case classNumber:
|
||||
switch value.value.(*object).class {
|
||||
case classStringName, classNumberName:
|
||||
default:
|
||||
continue
|
||||
}
|
||||
case valueString:
|
||||
case valueNumber:
|
||||
case valueString, valueNumber:
|
||||
default:
|
||||
continue
|
||||
}
|
||||
|
@ -138,21 +136,21 @@ func builtinJSON_stringify(call FunctionCall) Value {
|
|||
continue
|
||||
}
|
||||
seen[name] = true
|
||||
length += 1
|
||||
length++
|
||||
propertyList[index] = name
|
||||
}
|
||||
ctx.propertyList = propertyList[0:length]
|
||||
} else if replacer.class == classFunction {
|
||||
value := toValue_object(replacer)
|
||||
} else if replacer.class == classFunctionName {
|
||||
value := objectValue(replacer)
|
||||
ctx.replacerFunction = &value
|
||||
}
|
||||
}
|
||||
if spaceValue, exists := call.getArgument(2); exists {
|
||||
if spaceValue.kind == valueObject {
|
||||
switch spaceValue.value.(*_object).class {
|
||||
case classString:
|
||||
spaceValue = toValue_string(spaceValue.string())
|
||||
case classNumber:
|
||||
switch spaceValue.value.(*object).class {
|
||||
case classStringName:
|
||||
spaceValue = stringValue(spaceValue.string())
|
||||
case classNumberName:
|
||||
spaceValue = spaceValue.numberValue()
|
||||
}
|
||||
}
|
||||
|
@ -176,51 +174,51 @@ func builtinJSON_stringify(call FunctionCall) Value {
|
|||
}
|
||||
holder := call.runtime.newObject()
|
||||
holder.put("", call.Argument(0), false)
|
||||
value, exists := builtinJSON_stringifyWalk(ctx, "", holder)
|
||||
value, exists := builtinJSONStringifyWalk(ctx, "", holder)
|
||||
if !exists {
|
||||
return Value{}
|
||||
}
|
||||
valueJSON, err := json.Marshal(value)
|
||||
if err != nil {
|
||||
panic(call.runtime.panicTypeError(err.Error()))
|
||||
panic(call.runtime.panicTypeError("JSON.stringify marshal: %s", err))
|
||||
}
|
||||
if ctx.gap != "" {
|
||||
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()
|
||||
}
|
||||
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)
|
||||
|
||||
if value.IsObject() {
|
||||
object := value._object()
|
||||
if toJSON := object.get("toJSON"); toJSON.IsFunction() {
|
||||
obj := value.object()
|
||||
if toJSON := obj.get("toJSON"); toJSON.IsFunction() {
|
||||
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 object.objectClass.marshalJSON != nil {
|
||||
marshaler := object.objectClass.marshalJSON(object)
|
||||
marshaler := obj.objectClass.marshalJSON(obj)
|
||||
if marshaler != nil {
|
||||
return marshaler, true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
switch value.value.(*_object).class {
|
||||
case classBoolean:
|
||||
value = value._object().value.(Value)
|
||||
case classString:
|
||||
value = toValue_string(value.string())
|
||||
case classNumber:
|
||||
switch value.value.(*object).class {
|
||||
case classBooleanName:
|
||||
value = value.object().value.(Value)
|
||||
case classStringName:
|
||||
value = stringValue(value.string())
|
||||
case classNumberName:
|
||||
value = value.numberValue()
|
||||
}
|
||||
}
|
||||
|
@ -243,10 +241,10 @@ func builtinJSON_stringifyWalk(ctx _builtinJSON_stringifyContext, key string, ho
|
|||
case valueNull:
|
||||
return nil, true
|
||||
case valueObject:
|
||||
holder := value._object()
|
||||
if value := value._object(); nil != value {
|
||||
for _, object := range ctx.stack {
|
||||
if holder == object {
|
||||
holder := value.object()
|
||||
if value := value.object(); nil != value {
|
||||
for _, obj := range ctx.stack {
|
||||
if holder == obj {
|
||||
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)))
|
||||
}
|
||||
array := make([]interface{}, length)
|
||||
for index, _ := range array {
|
||||
for index := range array {
|
||||
name := arrayIndexToString(int64(index))
|
||||
value, _ := builtinJSON_stringifyWalk(ctx, name, holder)
|
||||
value, _ := builtinJSONStringifyWalk(ctx, name, holder)
|
||||
array[index] = value
|
||||
}
|
||||
return array, true
|
||||
} else if holder.class != classFunction {
|
||||
object := map[string]interface{}{}
|
||||
} else if holder.class != classFunctionName {
|
||||
obj := map[string]interface{}{}
|
||||
if ctx.propertyList != nil {
|
||||
for _, name := range ctx.propertyList {
|
||||
value, exists := builtinJSON_stringifyWalk(ctx, name, holder)
|
||||
value, exists := builtinJSONStringifyWalk(ctx, name, holder)
|
||||
if exists {
|
||||
object[name] = value
|
||||
obj[name] = value
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Go maps are without order, so this doesn't conform to the ECMA ordering
|
||||
// standard, but oh well...
|
||||
holder.enumerate(false, func(name string) bool {
|
||||
value, exists := builtinJSON_stringifyWalk(ctx, name, holder)
|
||||
value, exists := builtinJSONStringifyWalk(ctx, name, holder)
|
||||
if exists {
|
||||
object[name] = value
|
||||
obj[name] = value
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
||||
return object, true
|
||||
return obj, true
|
||||
}
|
||||
}
|
||||
return nil, false
|
||||
|
|
138
v1/vendor/github.com/robertkrimen/otto/builtin_math.go
generated
vendored
|
@ -7,27 +7,37 @@ import (
|
|||
|
||||
// Math
|
||||
|
||||
func builtinMath_abs(call FunctionCall) Value {
|
||||
func builtinMathAbs(call FunctionCall) Value {
|
||||
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()
|
||||
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()
|
||||
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()
|
||||
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()
|
||||
if math.IsNaN(y) {
|
||||
return NaNValue()
|
||||
|
@ -36,40 +46,75 @@ func builtinMath_atan2(call FunctionCall) Value {
|
|||
if math.IsNaN(x) {
|
||||
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()
|
||||
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()
|
||||
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()
|
||||
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()
|
||||
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()
|
||||
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) {
|
||||
case 0:
|
||||
return negativeInfinityValue()
|
||||
case 1:
|
||||
return toValue_float64(call.ArgumentList[0].float64())
|
||||
return float64Value(call.ArgumentList[0].float64())
|
||||
}
|
||||
result := call.ArgumentList[0].float64()
|
||||
if math.IsNaN(result) {
|
||||
|
@ -82,15 +127,15 @@ func builtinMath_max(call FunctionCall) 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) {
|
||||
case 0:
|
||||
return positiveInfinityValue()
|
||||
case 1:
|
||||
return toValue_float64(call.ArgumentList[0].float64())
|
||||
return float64Value(call.ArgumentList[0].float64())
|
||||
}
|
||||
result := call.ArgumentList[0].float64()
|
||||
if math.IsNaN(result) {
|
||||
|
@ -103,49 +148,64 @@ func builtinMath_min(call FunctionCall) 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)
|
||||
x := call.Argument(0).float64()
|
||||
y := call.Argument(1).float64()
|
||||
if math.Abs(x) == 1 && math.IsInf(y, 0) {
|
||||
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
|
||||
if call.runtime.random != nil {
|
||||
v = call.runtime.random()
|
||||
} 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()
|
||||
value := math.Floor(number + 0.5)
|
||||
if value == 0 {
|
||||
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()
|
||||
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()
|
||||
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()
|
||||
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 {
|
||||
return argumentList[0].numberValue()
|
||||
}
|
||||
return toValue_int(0)
|
||||
return intValue(0)
|
||||
}
|
||||
|
||||
func builtinNumber(call FunctionCall) Value {
|
||||
return numberValueFromNumberArgumentList(call.ArgumentList)
|
||||
}
|
||||
|
||||
func builtinNewNumber(self *_object, argumentList []Value) Value {
|
||||
return toValue_object(self.runtime.newNumber(numberValueFromNumberArgumentList(argumentList)))
|
||||
func builtinNewNumber(obj *object, argumentList []Value) Value {
|
||||
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
|
||||
value := call.thisClassObject(classNumber).primitiveValue()
|
||||
value := call.thisClassObject(classNumberName).primitiveValue()
|
||||
radix := 10
|
||||
radixArgument := call.Argument(0)
|
||||
if radixArgument.IsDefined() {
|
||||
|
@ -39,33 +39,32 @@ func builtinNumber_toString(call FunctionCall) Value {
|
|||
radix = int(integer)
|
||||
}
|
||||
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 {
|
||||
return call.thisClassObject(classNumber).primitiveValue()
|
||||
func builtinNumberValueOf(call FunctionCall) Value {
|
||||
return call.thisClassObject(classNumberName).primitiveValue()
|
||||
}
|
||||
|
||||
func builtinNumber_toFixed(call FunctionCall) Value {
|
||||
func builtinNumberToFixed(call FunctionCall) Value {
|
||||
precision := toIntegerFloat(call.Argument(0))
|
||||
if 20 < precision || 0 > precision {
|
||||
panic(call.runtime.panicRangeError("toFixed() precision must be between 0 and 20"))
|
||||
}
|
||||
if call.This.IsNaN() {
|
||||
return toValue_string("NaN")
|
||||
return stringValue("NaN")
|
||||
}
|
||||
value := call.This.float64()
|
||||
if math.Abs(value) >= 1e21 {
|
||||
return toValue_string(floatToString(value, 64))
|
||||
if value := call.This.float64(); math.Abs(value) >= 1e21 {
|
||||
return stringValue(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() {
|
||||
return toValue_string("NaN")
|
||||
return stringValue("NaN")
|
||||
}
|
||||
precision := float64(-1)
|
||||
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"))
|
||||
}
|
||||
}
|
||||
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() {
|
||||
return toValue_string("NaN")
|
||||
return stringValue("NaN")
|
||||
}
|
||||
value := call.Argument(0)
|
||||
if value.IsUndefined() {
|
||||
return toValue_string(call.This.string())
|
||||
return stringValue(call.This.string())
|
||||
}
|
||||
precision := toIntegerFloat(value)
|
||||
if 1 > precision {
|
||||
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 {
|
||||
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 {
|
||||
value := call.thisClassObject(classNumber).primitiveValue()
|
||||
func builtinNumberToLocaleString(call FunctionCall) Value {
|
||||
value := call.thisClassObject(classNumberName).primitiveValue()
|
||||
locale := call.Argument(0)
|
||||
lang := defaultLanguage
|
||||
if locale.IsDefined() {
|
||||
|
@ -108,5 +107,5 @@ func builtinNumber_toLocaleString(call FunctionCall) Value {
|
|||
}
|
||||
|
||||
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)
|
||||
switch value.kind {
|
||||
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)
|
||||
switch value.kind {
|
||||
case valueNull, valueUndefined:
|
||||
case valueNumber, valueString, valueBoolean:
|
||||
return toValue_object(self.runtime.toObject(value))
|
||||
return objectValue(obj.runtime.toObject(value))
|
||||
case valueObject:
|
||||
return value
|
||||
default:
|
||||
}
|
||||
return toValue_object(self.runtime.newObject())
|
||||
return objectValue(obj.runtime.newObject())
|
||||
}
|
||||
|
||||
func builtinObject_valueOf(call FunctionCall) Value {
|
||||
return toValue_object(call.thisObject())
|
||||
func builtinObjectValueOf(call FunctionCall) Value {
|
||||
return objectValue(call.thisObject())
|
||||
}
|
||||
|
||||
func builtinObject_hasOwnProperty(call FunctionCall) Value {
|
||||
func builtinObjectHasOwnProperty(call FunctionCall) Value {
|
||||
propertyName := call.Argument(0).string()
|
||||
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)
|
||||
if !value.IsObject() {
|
||||
return falseValue
|
||||
|
@ -55,235 +55,235 @@ func builtinObject_isPrototypeOf(call FunctionCall) Value {
|
|||
return falseValue
|
||||
}
|
||||
|
||||
func builtinObject_propertyIsEnumerable(call FunctionCall) Value {
|
||||
func builtinObjectPropertyIsEnumerable(call FunctionCall) Value {
|
||||
propertyName := call.Argument(0).string()
|
||||
thisObject := call.thisObject()
|
||||
property := thisObject.getOwnProperty(propertyName)
|
||||
if property != nil && property.enumerable() {
|
||||
prop := thisObject.getOwnProperty(propertyName)
|
||||
if prop != nil && prop.enumerable() {
|
||||
return trueValue
|
||||
}
|
||||
return falseValue
|
||||
}
|
||||
|
||||
func builtinObject_toString(call FunctionCall) Value {
|
||||
func builtinObjectToString(call FunctionCall) Value {
|
||||
var result string
|
||||
if call.This.IsUndefined() {
|
||||
switch {
|
||||
case call.This.IsUndefined():
|
||||
result = "[object Undefined]"
|
||||
} else if call.This.IsNull() {
|
||||
case call.This.IsNull():
|
||||
result = "[object Null]"
|
||||
} else {
|
||||
default:
|
||||
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")
|
||||
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)
|
||||
}
|
||||
|
||||
func builtinObject_getPrototypeOf(call FunctionCall) Value {
|
||||
objectValue := call.Argument(0)
|
||||
object := objectValue._object()
|
||||
if object == nil {
|
||||
panic(call.runtime.panicTypeError())
|
||||
func builtinObjectGetPrototypeOf(call FunctionCall) Value {
|
||||
val := call.Argument(0)
|
||||
obj := val.object()
|
||||
if obj == nil {
|
||||
panic(call.runtime.panicTypeError("Object.GetPrototypeOf is nil"))
|
||||
}
|
||||
|
||||
if object.prototype == nil {
|
||||
if obj.prototype == nil {
|
||||
return nullValue
|
||||
}
|
||||
|
||||
return toValue_object(object.prototype)
|
||||
return objectValue(obj.prototype)
|
||||
}
|
||||
|
||||
func builtinObject_getOwnPropertyDescriptor(call FunctionCall) Value {
|
||||
objectValue := call.Argument(0)
|
||||
object := objectValue._object()
|
||||
if object == nil {
|
||||
panic(call.runtime.panicTypeError())
|
||||
func builtinObjectGetOwnPropertyDescriptor(call FunctionCall) Value {
|
||||
val := call.Argument(0)
|
||||
obj := val.object()
|
||||
if obj == nil {
|
||||
panic(call.runtime.panicTypeError("Object.GetOwnPropertyDescriptor is nil"))
|
||||
}
|
||||
|
||||
name := call.Argument(1).string()
|
||||
descriptor := object.getOwnProperty(name)
|
||||
descriptor := obj.getOwnProperty(name)
|
||||
if descriptor == nil {
|
||||
return Value{}
|
||||
}
|
||||
return toValue_object(call.runtime.fromPropertyDescriptor(*descriptor))
|
||||
return objectValue(call.runtime.fromPropertyDescriptor(*descriptor))
|
||||
}
|
||||
|
||||
func builtinObject_defineProperty(call FunctionCall) Value {
|
||||
objectValue := call.Argument(0)
|
||||
object := objectValue._object()
|
||||
if object == nil {
|
||||
panic(call.runtime.panicTypeError())
|
||||
func builtinObjectDefineProperty(call FunctionCall) Value {
|
||||
val := call.Argument(0)
|
||||
obj := val.object()
|
||||
if obj == nil {
|
||||
panic(call.runtime.panicTypeError("Object.DefineProperty is nil"))
|
||||
}
|
||||
name := call.Argument(1).string()
|
||||
descriptor := toPropertyDescriptor(call.runtime, call.Argument(2))
|
||||
object.defineOwnProperty(name, descriptor, true)
|
||||
return objectValue
|
||||
obj.defineOwnProperty(name, descriptor, true)
|
||||
return val
|
||||
}
|
||||
|
||||
func builtinObject_defineProperties(call FunctionCall) Value {
|
||||
objectValue := call.Argument(0)
|
||||
object := objectValue._object()
|
||||
if object == nil {
|
||||
panic(call.runtime.panicTypeError())
|
||||
func builtinObjectDefineProperties(call FunctionCall) Value {
|
||||
val := call.Argument(0)
|
||||
obj := val.object()
|
||||
if obj == nil {
|
||||
panic(call.runtime.panicTypeError("Object.DefineProperties is nil"))
|
||||
}
|
||||
|
||||
properties := call.runtime.toObject(call.Argument(1))
|
||||
properties.enumerate(false, func(name string) bool {
|
||||
descriptor := toPropertyDescriptor(call.runtime, properties.get(name))
|
||||
object.defineOwnProperty(name, descriptor, true)
|
||||
obj.defineOwnProperty(name, descriptor, true)
|
||||
return true
|
||||
})
|
||||
|
||||
return objectValue
|
||||
return val
|
||||
}
|
||||
|
||||
func builtinObject_create(call FunctionCall) Value {
|
||||
func builtinObjectCreate(call FunctionCall) Value {
|
||||
prototypeValue := call.Argument(0)
|
||||
if !prototypeValue.IsNull() && !prototypeValue.IsObject() {
|
||||
panic(call.runtime.panicTypeError())
|
||||
panic(call.runtime.panicTypeError("Object.Create is nil"))
|
||||
}
|
||||
|
||||
object := call.runtime.newObject()
|
||||
object.prototype = prototypeValue._object()
|
||||
obj := call.runtime.newObject()
|
||||
obj.prototype = prototypeValue.object()
|
||||
|
||||
propertiesValue := call.Argument(1)
|
||||
if propertiesValue.IsDefined() {
|
||||
properties := call.runtime.toObject(propertiesValue)
|
||||
properties.enumerate(false, func(name string) bool {
|
||||
descriptor := toPropertyDescriptor(call.runtime, properties.get(name))
|
||||
object.defineOwnProperty(name, descriptor, true)
|
||||
obj.defineOwnProperty(name, descriptor, true)
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
return toValue_object(object)
|
||||
return objectValue(obj)
|
||||
}
|
||||
|
||||
func builtinObject_isExtensible(call FunctionCall) Value {
|
||||
object := call.Argument(0)
|
||||
if object := object._object(); object != nil {
|
||||
return toValue_bool(object.extensible)
|
||||
func builtinObjectIsExtensible(call FunctionCall) Value {
|
||||
val := call.Argument(0)
|
||||
if obj := val.object(); obj != nil {
|
||||
return boolValue(obj.extensible)
|
||||
}
|
||||
panic(call.runtime.panicTypeError())
|
||||
panic(call.runtime.panicTypeError("Object.IsExtensible is nil"))
|
||||
}
|
||||
|
||||
func builtinObject_preventExtensions(call FunctionCall) Value {
|
||||
object := call.Argument(0)
|
||||
if object := object._object(); object != nil {
|
||||
object.extensible = false
|
||||
} else {
|
||||
panic(call.runtime.panicTypeError())
|
||||
func builtinObjectPreventExtensions(call FunctionCall) Value {
|
||||
val := call.Argument(0)
|
||||
if obj := val.object(); obj != nil {
|
||||
obj.extensible = false
|
||||
return val
|
||||
}
|
||||
return object
|
||||
panic(call.runtime.panicTypeError("Object.PreventExtensions is nil"))
|
||||
}
|
||||
|
||||
func builtinObject_isSealed(call FunctionCall) Value {
|
||||
object := call.Argument(0)
|
||||
if object := object._object(); object != nil {
|
||||
if object.extensible {
|
||||
return toValue_bool(false)
|
||||
func builtinObjectIsSealed(call FunctionCall) Value {
|
||||
val := call.Argument(0)
|
||||
if obj := val.object(); obj != nil {
|
||||
if obj.extensible {
|
||||
return boolValue(false)
|
||||
}
|
||||
result := true
|
||||
object.enumerate(true, func(name string) bool {
|
||||
property := object.getProperty(name)
|
||||
if property.configurable() {
|
||||
obj.enumerate(true, func(name string) bool {
|
||||
prop := obj.getProperty(name)
|
||||
if prop.configurable() {
|
||||
result = false
|
||||
}
|
||||
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 {
|
||||
object := call.Argument(0)
|
||||
if object := object._object(); object != nil {
|
||||
object.enumerate(true, func(name string) bool {
|
||||
if property := object.getOwnProperty(name); nil != property && property.configurable() {
|
||||
property.configureOff()
|
||||
object.defineOwnProperty(name, *property, true)
|
||||
func builtinObjectSeal(call FunctionCall) Value {
|
||||
val := call.Argument(0)
|
||||
if obj := val.object(); obj != nil {
|
||||
obj.enumerate(true, func(name string) bool {
|
||||
if prop := obj.getOwnProperty(name); nil != prop && prop.configurable() {
|
||||
prop.configureOff()
|
||||
obj.defineOwnProperty(name, *prop, true)
|
||||
}
|
||||
return true
|
||||
})
|
||||
object.extensible = false
|
||||
} else {
|
||||
panic(call.runtime.panicTypeError())
|
||||
obj.extensible = false
|
||||
return val
|
||||
}
|
||||
return object
|
||||
panic(call.runtime.panicTypeError("Object.Seal is nil"))
|
||||
}
|
||||
|
||||
func builtinObject_isFrozen(call FunctionCall) Value {
|
||||
object := call.Argument(0)
|
||||
if object := object._object(); object != nil {
|
||||
if object.extensible {
|
||||
return toValue_bool(false)
|
||||
func builtinObjectIsFrozen(call FunctionCall) Value {
|
||||
val := call.Argument(0)
|
||||
if obj := val.object(); obj != nil {
|
||||
if obj.extensible {
|
||||
return boolValue(false)
|
||||
}
|
||||
result := true
|
||||
object.enumerate(true, func(name string) bool {
|
||||
property := object.getProperty(name)
|
||||
if property.configurable() || property.writable() {
|
||||
obj.enumerate(true, func(name string) bool {
|
||||
prop := obj.getProperty(name)
|
||||
if prop.configurable() || prop.writable() {
|
||||
result = false
|
||||
}
|
||||
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 {
|
||||
object := call.Argument(0)
|
||||
if object := object._object(); object != nil {
|
||||
object.enumerate(true, func(name string) bool {
|
||||
if property, update := object.getOwnProperty(name), false; nil != property {
|
||||
if property.isDataDescriptor() && property.writable() {
|
||||
property.writeOff()
|
||||
func builtinObjectFreeze(call FunctionCall) Value {
|
||||
val := call.Argument(0)
|
||||
if obj := val.object(); obj != nil {
|
||||
obj.enumerate(true, func(name string) bool {
|
||||
if prop, update := obj.getOwnProperty(name), false; nil != prop {
|
||||
if prop.isDataDescriptor() && prop.writable() {
|
||||
prop.writeOff()
|
||||
update = true
|
||||
}
|
||||
if property.configurable() {
|
||||
property.configureOff()
|
||||
if prop.configurable() {
|
||||
prop.configureOff()
|
||||
update = true
|
||||
}
|
||||
if update {
|
||||
object.defineOwnProperty(name, *property, true)
|
||||
obj.defineOwnProperty(name, *prop, true)
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
object.extensible = false
|
||||
} else {
|
||||
panic(call.runtime.panicTypeError())
|
||||
obj.extensible = false
|
||||
return val
|
||||
}
|
||||
return object
|
||||
panic(call.runtime.panicTypeError("Object.Freeze is nil"))
|
||||
}
|
||||
|
||||
func builtinObject_keys(call FunctionCall) Value {
|
||||
if object, keys := call.Argument(0)._object(), []Value(nil); nil != object {
|
||||
object.enumerate(false, func(name string) bool {
|
||||
keys = append(keys, toValue_string(name))
|
||||
func builtinObjectKeys(call FunctionCall) Value {
|
||||
if obj, keys := call.Argument(0).object(), []Value(nil); nil != obj {
|
||||
obj.enumerate(false, func(name string) bool {
|
||||
keys = append(keys, stringValue(name))
|
||||
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 {
|
||||
if object, propertyNames := call.Argument(0)._object(), []Value(nil); nil != object {
|
||||
object.enumerate(true, func(name string) bool {
|
||||
if object.hasOwnProperty(name) {
|
||||
propertyNames = append(propertyNames, toValue_string(name))
|
||||
func builtinObjectGetOwnPropertyNames(call FunctionCall) Value {
|
||||
if obj, propertyNames := call.Argument(0).object(), []Value(nil); nil != obj {
|
||||
obj.enumerate(true, func(name string) bool {
|
||||
if obj.hasOwnProperty(name) {
|
||||
propertyNames = append(propertyNames, stringValue(name))
|
||||
}
|
||||
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 {
|
||||
pattern := call.Argument(0)
|
||||
flags := call.Argument(1)
|
||||
if object := pattern._object(); object != nil {
|
||||
if object.class == classRegExp && flags.IsUndefined() {
|
||||
if obj := pattern.object(); obj != nil {
|
||||
if obj.class == classRegExpName && flags.IsUndefined() {
|
||||
return pattern
|
||||
}
|
||||
}
|
||||
return toValue_object(call.runtime.newRegExp(pattern, flags))
|
||||
return objectValue(call.runtime.newRegExp(pattern, flags))
|
||||
}
|
||||
|
||||
func builtinNewRegExp(self *_object, argumentList []Value) Value {
|
||||
return toValue_object(self.runtime.newRegExp(
|
||||
func builtinNewRegExp(obj *object, argumentList []Value) Value {
|
||||
return objectValue(obj.runtime.newRegExp(
|
||||
valueOfArrayIndex(argumentList, 0),
|
||||
valueOfArrayIndex(argumentList, 1),
|
||||
))
|
||||
}
|
||||
|
||||
func builtinRegExp_toString(call FunctionCall) Value {
|
||||
func builtinRegExpToString(call FunctionCall) Value {
|
||||
thisObject := call.thisObject()
|
||||
source := thisObject.get("source").string()
|
||||
flags := []byte{}
|
||||
|
@ -37,41 +37,47 @@ func builtinRegExp_toString(call FunctionCall) Value {
|
|||
if thisObject.get("multiline").bool() {
|
||||
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()
|
||||
target := call.Argument(0).string()
|
||||
match, result := execRegExp(thisObject, target)
|
||||
if !match {
|
||||
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()
|
||||
target := call.Argument(0).string()
|
||||
match, result := execRegExp(thisObject, target)
|
||||
|
||||
if !match {
|
||||
return toValue_bool(match)
|
||||
return boolValue(match)
|
||||
}
|
||||
|
||||
// Match extract and assign input, $_ and $1 -> $9 on global RegExp.
|
||||
input := toValue_string(target)
|
||||
call.runtime.global.RegExp.defineProperty("$_", input, 0100, false)
|
||||
call.runtime.global.RegExp.defineProperty("input", input, 0100, false)
|
||||
input := stringValue(target)
|
||||
call.runtime.global.RegExp.defineProperty("$_", input, 0o100, false)
|
||||
call.runtime.global.RegExp.defineProperty("input", input, 0o100, false)
|
||||
|
||||
var start int
|
||||
n := 1
|
||||
re := call.runtime.global.RegExp
|
||||
empty := stringValue("")
|
||||
for i, v := range result[2:] {
|
||||
if i%2 == 0 {
|
||||
start = v
|
||||
} 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++
|
||||
if n == 10 {
|
||||
break
|
||||
|
@ -81,16 +87,15 @@ func builtinRegExp_test(call FunctionCall) Value {
|
|||
|
||||
if n <= 9 {
|
||||
// Erase remaining.
|
||||
empty := toValue_string("")
|
||||
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
|
||||
// semblance of compatibility.
|
||||
// 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 {
|
||||
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 {
|
||||
return stringValueFromStringArgumentList(call.ArgumentList)
|
||||
}
|
||||
|
||||
func builtinNewString(self *_object, argumentList []Value) Value {
|
||||
return toValue_object(self.runtime.newString(stringValueFromStringArgumentList(argumentList)))
|
||||
func builtinNewString(obj *object, argumentList []Value) Value {
|
||||
return objectValue(obj.runtime.newString(stringValueFromStringArgumentList(argumentList)))
|
||||
}
|
||||
|
||||
func builtinString_toString(call FunctionCall) Value {
|
||||
return call.thisClassObject(classString).primitiveValue()
|
||||
}
|
||||
func builtinString_valueOf(call FunctionCall) Value {
|
||||
return call.thisClassObject(classString).primitiveValue()
|
||||
func builtinStringToString(call FunctionCall) Value {
|
||||
return call.thisClassObject(classStringName).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))
|
||||
for index, value := range call.ArgumentList {
|
||||
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)
|
||||
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 {
|
||||
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)
|
||||
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 {
|
||||
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)
|
||||
var value bytes.Buffer
|
||||
value.WriteString(call.This.string())
|
||||
for _, item := range call.ArgumentList {
|
||||
value.WriteString(item.string())
|
||||
}
|
||||
return toValue_string(value.String())
|
||||
return stringValue(value.String())
|
||||
}
|
||||
|
||||
func lastIndexRune(s, substr string) int {
|
||||
|
@ -89,44 +90,44 @@ func utf16Length(s string) int {
|
|||
return len(utf16.Encode([]rune(s)))
|
||||
}
|
||||
|
||||
func builtinString_indexOf(call FunctionCall) Value {
|
||||
func builtinStringIndexOf(call FunctionCall) Value {
|
||||
checkObjectCoercible(call.runtime, call.This)
|
||||
value := call.This.string()
|
||||
target := call.Argument(0).string()
|
||||
if 2 > len(call.ArgumentList) {
|
||||
return toValue_int(indexRune(value, target))
|
||||
return intValue(indexRune(value, target))
|
||||
}
|
||||
start := toIntegerFloat(call.Argument(1))
|
||||
if 0 > start {
|
||||
start = 0
|
||||
} else if start >= float64(len(value)) {
|
||||
if target == "" {
|
||||
return toValue_int(len(value))
|
||||
return intValue(len(value))
|
||||
}
|
||||
return toValue_int(-1)
|
||||
return intValue(-1)
|
||||
}
|
||||
index := indexRune(value[int(start):], target)
|
||||
if index >= 0 {
|
||||
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)
|
||||
value := call.This.string()
|
||||
target := call.Argument(0).string()
|
||||
if 2 > len(call.ArgumentList) || call.ArgumentList[1].IsUndefined() {
|
||||
return toValue_int(lastIndexRune(value, target))
|
||||
return intValue(lastIndexRune(value, target))
|
||||
}
|
||||
length := len(value)
|
||||
if length == 0 {
|
||||
return toValue_int(lastIndexRune(value, target))
|
||||
return intValue(lastIndexRune(value, target))
|
||||
}
|
||||
start := call.ArgumentList[1].number()
|
||||
if start.kind == numberInfinity { // FIXME
|
||||
// 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 {
|
||||
start.int64 = 0
|
||||
|
@ -135,15 +136,15 @@ func builtinString_lastIndexOf(call FunctionCall) Value {
|
|||
if 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)
|
||||
target := call.This.string()
|
||||
matcherValue := call.Argument(0)
|
||||
matcher := matcherValue._object()
|
||||
if !matcherValue.IsObject() || matcher.class != classRegExp {
|
||||
matcher := matcherValue.object()
|
||||
if !matcherValue.IsObject() || matcher.class != classRegExpName {
|
||||
matcher = call.runtime.newRegExp(matcherValue, Value{})
|
||||
}
|
||||
global := matcher.get("global").bool()
|
||||
|
@ -152,34 +153,32 @@ func builtinString_match(call FunctionCall) Value {
|
|||
if !match {
|
||||
return nullValue
|
||||
}
|
||||
return toValue_object(execResultToArray(call.runtime, target, result))
|
||||
return objectValue(execResultToArray(call.runtime, target, result))
|
||||
}
|
||||
|
||||
{
|
||||
result := matcher.regExpValue().regularExpression.FindAllStringIndex(target, -1)
|
||||
if result == nil {
|
||||
matcher.put("lastIndex", toValue_int(0), true)
|
||||
matcher.put("lastIndex", intValue(0), true)
|
||||
return Value{} // !match
|
||||
}
|
||||
matchCount := len(result)
|
||||
valueArray := make([]Value, matchCount)
|
||||
for index := 0; index < matchCount; index++ {
|
||||
valueArray[index] = toValue_string(target[result[index][0]:result[index][1]])
|
||||
}
|
||||
matcher.put("lastIndex", toValue_int(result[matchCount-1][1]), true)
|
||||
return toValue_object(call.runtime.newArrayOf(valueArray))
|
||||
valueArray[index] = stringValue(target[result[index][0]:result[index][1]])
|
||||
}
|
||||
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
|
||||
output = input
|
||||
output := input
|
||||
if match[0] != lastIndex {
|
||||
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
|
||||
switch part[1] {
|
||||
case '$':
|
||||
|
@ -193,37 +192,38 @@ func builtinString_findAndReplaceString(input []byte, lastIndex int, match []int
|
|||
}
|
||||
matchNumberParse, err := strconv.ParseInt(string(part[1:]), 10, 64)
|
||||
if err != nil {
|
||||
return []byte{}
|
||||
return nil
|
||||
}
|
||||
matchNumber := int(matchNumberParse)
|
||||
if matchNumber >= matchCount {
|
||||
return []byte{}
|
||||
return nil
|
||||
}
|
||||
offset := 2 * matchNumber
|
||||
if 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)
|
||||
target := []byte(call.This.string())
|
||||
searchValue := call.Argument(0)
|
||||
searchObject := searchValue._object()
|
||||
searchObject := searchValue.object()
|
||||
|
||||
// TODO If a capture is -1?
|
||||
var search *regexp.Regexp
|
||||
global := false
|
||||
find := 1
|
||||
if searchValue.IsObject() && searchObject.class == classRegExp {
|
||||
if searchValue.IsObject() && searchObject.class == classRegExpName {
|
||||
regExp := searchObject.regExpValue()
|
||||
search = regExp.regularExpression
|
||||
if regExp.global {
|
||||
find = -1
|
||||
global = true
|
||||
}
|
||||
} else {
|
||||
search = regexp.MustCompile(regexp.QuoteMeta(searchValue.string()))
|
||||
|
@ -231,17 +231,15 @@ func builtinString_replace(call FunctionCall) Value {
|
|||
|
||||
found := search.FindAllSubmatchIndex(target, find)
|
||||
if found == nil {
|
||||
return toValue_string(string(target)) // !match
|
||||
return stringValue(string(target)) // !match
|
||||
}
|
||||
|
||||
{
|
||||
lastIndex := 0
|
||||
result := []byte{}
|
||||
|
||||
replaceValue := call.Argument(1)
|
||||
if replaceValue.isCallable() {
|
||||
target := string(target)
|
||||
replace := replaceValue._object()
|
||||
replace := replaceValue.object()
|
||||
for _, match := range found {
|
||||
if match[0] != lastIndex {
|
||||
result = append(result, target[lastIndex:match[0]]...)
|
||||
|
@ -251,13 +249,13 @@ func builtinString_replace(call FunctionCall) Value {
|
|||
for index := 0; index < matchCount; index++ {
|
||||
offset := 2 * index
|
||||
if match[offset] != -1 {
|
||||
argumentList[index] = toValue_string(target[match[offset]:match[offset+1]])
|
||||
argumentList[index] = stringValue(target[match[offset]:match[offset+1]])
|
||||
} else {
|
||||
argumentList[index] = Value{}
|
||||
}
|
||||
}
|
||||
argumentList[matchCount+0] = toValue_int(match[0])
|
||||
argumentList[matchCount+1] = toValue_string(target)
|
||||
argumentList[matchCount+0] = intValue(match[0])
|
||||
argumentList[matchCount+1] = stringValue(target)
|
||||
replacement := replace.call(Value{}, argumentList, false, nativeFrame).string()
|
||||
result = append(result, []byte(replacement)...)
|
||||
lastIndex = match[1]
|
||||
|
@ -265,7 +263,7 @@ func builtinString_replace(call FunctionCall) Value {
|
|||
} else {
|
||||
replace := []byte(replaceValue.string())
|
||||
for _, match := range found {
|
||||
result = builtinString_findAndReplaceString(result, lastIndex, match, target, replace)
|
||||
result = builtinStringFindAndReplaceString(result, lastIndex, match, target, replace)
|
||||
lastIndex = match[1]
|
||||
}
|
||||
}
|
||||
|
@ -275,29 +273,28 @@ func builtinString_replace(call FunctionCall) Value {
|
|||
}
|
||||
|
||||
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)
|
||||
target := call.This.string()
|
||||
searchValue := call.Argument(0)
|
||||
search := searchValue._object()
|
||||
if !searchValue.IsObject() || search.class != classRegExp {
|
||||
search := searchValue.object()
|
||||
if !searchValue.IsObject() || search.class != classRegExpName {
|
||||
search = call.runtime.newRegExp(searchValue, Value{})
|
||||
}
|
||||
result := search.regExpValue().regularExpression.FindStringIndex(target)
|
||||
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)
|
||||
target := call.This.string()
|
||||
|
||||
|
@ -309,16 +306,16 @@ func builtinString_split(call FunctionCall) Value {
|
|||
}
|
||||
|
||||
if limit == 0 {
|
||||
return toValue_object(call.runtime.newArray(0))
|
||||
return objectValue(call.runtime.newArray(0))
|
||||
}
|
||||
|
||||
if separatorValue.IsUndefined() {
|
||||
return toValue_object(call.runtime.newArrayOf([]Value{toValue_string(target)}))
|
||||
return objectValue(call.runtime.newArrayOf([]Value{stringValue(target)}))
|
||||
}
|
||||
|
||||
if separatorValue.isRegExp() {
|
||||
targetLength := len(target)
|
||||
search := separatorValue._object().regExpValue().regularExpression
|
||||
search := separatorValue.object().regExpValue().regularExpression
|
||||
valueArray := []Value{}
|
||||
result := search.FindAllStringSubmatchIndex(target, -1)
|
||||
lastIndex := 0
|
||||
|
@ -333,11 +330,11 @@ func builtinString_split(call FunctionCall) Value {
|
|||
}
|
||||
|
||||
if lastIndex != match[0] {
|
||||
valueArray = append(valueArray, toValue_string(target[lastIndex:match[0]]))
|
||||
valueArray = append(valueArray, stringValue(target[lastIndex:match[0]]))
|
||||
found++
|
||||
} else if lastIndex == match[0] {
|
||||
if lastIndex != -1 {
|
||||
valueArray = append(valueArray, toValue_string(""))
|
||||
valueArray = append(valueArray, stringValue(""))
|
||||
found++
|
||||
}
|
||||
}
|
||||
|
@ -352,7 +349,7 @@ func builtinString_split(call FunctionCall) Value {
|
|||
offset := index * 2
|
||||
value := Value{}
|
||||
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)
|
||||
found++
|
||||
|
@ -364,14 +361,14 @@ func builtinString_split(call FunctionCall) Value {
|
|||
|
||||
if found != limit {
|
||||
if lastIndex != targetLength {
|
||||
valueArray = append(valueArray, toValue_string(target[lastIndex:targetLength]))
|
||||
valueArray = append(valueArray, stringValue(target[lastIndex:targetLength]))
|
||||
} else {
|
||||
valueArray = append(valueArray, toValue_string(""))
|
||||
valueArray = append(valueArray, stringValue(""))
|
||||
}
|
||||
}
|
||||
|
||||
RETURN:
|
||||
return toValue_object(call.runtime.newArrayOf(valueArray))
|
||||
return objectValue(call.runtime.newArrayOf(valueArray))
|
||||
} else {
|
||||
separator := separatorValue.string()
|
||||
|
||||
|
@ -390,26 +387,26 @@ func builtinString_split(call FunctionCall) Value {
|
|||
|
||||
valueArray := make([]Value, len(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)
|
||||
target := call.This.string()
|
||||
|
||||
length := int64(len(target))
|
||||
start, end := rangeStartEnd(call.ArgumentList, length, false)
|
||||
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)
|
||||
target := []rune(call.This.string())
|
||||
|
||||
|
@ -418,21 +415,21 @@ func builtinString_substring(call FunctionCall) Value {
|
|||
if start > end {
|
||||
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())
|
||||
|
||||
size := int64(len(target))
|
||||
start, length := rangeStartLength(call.ArgumentList, size)
|
||||
|
||||
if start >= size {
|
||||
return toValue_string("")
|
||||
return stringValue("")
|
||||
}
|
||||
|
||||
if length <= 0 {
|
||||
return toValue_string("")
|
||||
return stringValue("")
|
||||
}
|
||||
|
||||
if start+length >= size {
|
||||
|
@ -443,66 +440,69 @@ func builtinString_substr(call FunctionCall) Value {
|
|||
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)
|
||||
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)
|
||||
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
|
||||
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"
|
||||
func builtinStringToUpperCase(call FunctionCall) Value {
|
||||
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)
|
||||
return toValue(strings.Trim(call.This.string(),
|
||||
builtinString_trim_whitespace))
|
||||
builtinStringTrimWhitespace))
|
||||
}
|
||||
|
||||
// Mozilla extension, not ECMAScript 5
|
||||
func builtinString_trimLeft(call FunctionCall) Value {
|
||||
// Mozilla extension, not ECMAScript 5.
|
||||
func builtinStringTrimLeft(call FunctionCall) Value {
|
||||
checkObjectCoercible(call.runtime, call.This)
|
||||
return toValue(strings.TrimLeft(call.This.string(),
|
||||
builtinString_trim_whitespace))
|
||||
builtinStringTrimWhitespace))
|
||||
}
|
||||
|
||||
// Mozilla extension, not ECMAScript 5
|
||||
func builtinString_trimRight(call FunctionCall) Value {
|
||||
// Mozilla extension, not ECMAScript 5.
|
||||
func builtinStringTrimRight(call FunctionCall) Value {
|
||||
checkObjectCoercible(call.runtime, call.This)
|
||||
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)
|
||||
this := call.This.string()
|
||||
this := call.This.string() //nolint: ifshort
|
||||
that := call.Argument(0).string()
|
||||
if this < that {
|
||||
return toValue_int(-1)
|
||||
return intValue(-1)
|
||||
} else if this == that {
|
||||
return toValue_int(0)
|
||||
return intValue(0)
|
||||
}
|
||||
return toValue_int(1)
|
||||
return intValue(1)
|
||||
}
|
||||
|
||||
/*
|
||||
An alternate version of String.trim
|
||||
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 builtinStringToLocaleLowerCase(call FunctionCall) Value {
|
||||
return builtinStringToLowerCase(call)
|
||||
}
|
||||
|
||||
func builtinString_toLocaleUpperCase(call FunctionCall) Value {
|
||||
return builtinString_toUpperCase(call)
|
||||
func builtinStringToLocaleUpperCase(call FunctionCall) Value {
|
||||
return builtinStringToUpperCase(call)
|
||||
}
|
||||
|
|
183
v1/vendor/github.com/robertkrimen/otto/clone.go
generated
vendored
|
@ -4,158 +4,157 @@ import (
|
|||
"fmt"
|
||||
)
|
||||
|
||||
type _clone struct {
|
||||
runtime *_runtime
|
||||
_object map[*_object]*_object
|
||||
_objectStash map[*_objectStash]*_objectStash
|
||||
_dclStash map[*_dclStash]*_dclStash
|
||||
_fnStash map[*_fnStash]*_fnStash
|
||||
type cloner struct {
|
||||
runtime *runtime
|
||||
obj map[*object]*object
|
||||
objectstash map[*objectStash]*objectStash
|
||||
dclstash map[*dclStash]*dclStash
|
||||
fnstash map[*fnStash]*fnStash
|
||||
}
|
||||
|
||||
func (in *_runtime) clone() *_runtime {
|
||||
in.lck.Lock()
|
||||
defer in.lck.Unlock()
|
||||
func (rt *runtime) clone() *runtime {
|
||||
rt.lck.Lock()
|
||||
defer rt.lck.Unlock()
|
||||
|
||||
out := &_runtime{
|
||||
debugger: in.debugger,
|
||||
random: in.random,
|
||||
stackLimit: in.stackLimit,
|
||||
traceLimit: in.traceLimit,
|
||||
out := &runtime{
|
||||
debugger: rt.debugger,
|
||||
random: rt.random,
|
||||
stackLimit: rt.stackLimit,
|
||||
traceLimit: rt.traceLimit,
|
||||
}
|
||||
|
||||
clone := _clone{
|
||||
c := cloner{
|
||||
runtime: out,
|
||||
_object: make(map[*_object]*_object),
|
||||
_objectStash: make(map[*_objectStash]*_objectStash),
|
||||
_dclStash: make(map[*_dclStash]*_dclStash),
|
||||
_fnStash: make(map[*_fnStash]*_fnStash),
|
||||
obj: make(map[*object]*object),
|
||||
objectstash: make(map[*objectStash]*objectStash),
|
||||
dclstash: make(map[*dclStash]*dclStash),
|
||||
fnstash: make(map[*fnStash]*fnStash),
|
||||
}
|
||||
|
||||
globalObject := clone.object(in.globalObject)
|
||||
globalObject := c.object(rt.globalObject)
|
||||
out.globalStash = out.newObjectStash(globalObject, nil)
|
||||
out.globalObject = globalObject
|
||||
out.global = _global{
|
||||
clone.object(in.global.Object),
|
||||
clone.object(in.global.Function),
|
||||
clone.object(in.global.Array),
|
||||
clone.object(in.global.String),
|
||||
clone.object(in.global.Boolean),
|
||||
clone.object(in.global.Number),
|
||||
clone.object(in.global.Math),
|
||||
clone.object(in.global.Date),
|
||||
clone.object(in.global.RegExp),
|
||||
clone.object(in.global.Error),
|
||||
clone.object(in.global.EvalError),
|
||||
clone.object(in.global.TypeError),
|
||||
clone.object(in.global.RangeError),
|
||||
clone.object(in.global.ReferenceError),
|
||||
clone.object(in.global.SyntaxError),
|
||||
clone.object(in.global.URIError),
|
||||
clone.object(in.global.JSON),
|
||||
out.global = global{
|
||||
c.object(rt.global.Object),
|
||||
c.object(rt.global.Function),
|
||||
c.object(rt.global.Array),
|
||||
c.object(rt.global.String),
|
||||
c.object(rt.global.Boolean),
|
||||
c.object(rt.global.Number),
|
||||
c.object(rt.global.Math),
|
||||
c.object(rt.global.Date),
|
||||
c.object(rt.global.RegExp),
|
||||
c.object(rt.global.Error),
|
||||
c.object(rt.global.EvalError),
|
||||
c.object(rt.global.TypeError),
|
||||
c.object(rt.global.RangeError),
|
||||
c.object(rt.global.ReferenceError),
|
||||
c.object(rt.global.SyntaxError),
|
||||
c.object(rt.global.URIError),
|
||||
c.object(rt.global.JSON),
|
||||
|
||||
clone.object(in.global.ObjectPrototype),
|
||||
clone.object(in.global.FunctionPrototype),
|
||||
clone.object(in.global.ArrayPrototype),
|
||||
clone.object(in.global.StringPrototype),
|
||||
clone.object(in.global.BooleanPrototype),
|
||||
clone.object(in.global.NumberPrototype),
|
||||
clone.object(in.global.DatePrototype),
|
||||
clone.object(in.global.RegExpPrototype),
|
||||
clone.object(in.global.ErrorPrototype),
|
||||
clone.object(in.global.EvalErrorPrototype),
|
||||
clone.object(in.global.TypeErrorPrototype),
|
||||
clone.object(in.global.RangeErrorPrototype),
|
||||
clone.object(in.global.ReferenceErrorPrototype),
|
||||
clone.object(in.global.SyntaxErrorPrototype),
|
||||
clone.object(in.global.URIErrorPrototype),
|
||||
c.object(rt.global.ObjectPrototype),
|
||||
c.object(rt.global.FunctionPrototype),
|
||||
c.object(rt.global.ArrayPrototype),
|
||||
c.object(rt.global.StringPrototype),
|
||||
c.object(rt.global.BooleanPrototype),
|
||||
c.object(rt.global.NumberPrototype),
|
||||
c.object(rt.global.DatePrototype),
|
||||
c.object(rt.global.RegExpPrototype),
|
||||
c.object(rt.global.ErrorPrototype),
|
||||
c.object(rt.global.EvalErrorPrototype),
|
||||
c.object(rt.global.TypeErrorPrototype),
|
||||
c.object(rt.global.RangeErrorPrototype),
|
||||
c.object(rt.global.ReferenceErrorPrototype),
|
||||
c.object(rt.global.SyntaxErrorPrototype),
|
||||
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
|
||||
|
||||
// Not sure if this is necessary, but give some help to the GC
|
||||
clone.runtime = nil
|
||||
clone._object = nil
|
||||
clone._objectStash = nil
|
||||
clone._dclStash = nil
|
||||
clone._fnStash = nil
|
||||
c.runtime = nil
|
||||
c.obj = nil
|
||||
c.objectstash = nil
|
||||
c.dclstash = nil
|
||||
c.fnstash = nil
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
func (clone *_clone) object(in *_object) *_object {
|
||||
if out, exists := clone._object[in]; exists {
|
||||
func (c *cloner) object(in *object) *object {
|
||||
if out, exists := c.obj[in]; exists {
|
||||
return out
|
||||
}
|
||||
out := &_object{}
|
||||
clone._object[in] = out
|
||||
return in.objectClass.clone(in, out, clone)
|
||||
out := &object{}
|
||||
c.obj[in] = out
|
||||
return in.objectClass.clone(in, out, c)
|
||||
}
|
||||
|
||||
func (clone *_clone) dclStash(in *_dclStash) (*_dclStash, bool) {
|
||||
if out, exists := clone._dclStash[in]; exists {
|
||||
func (c *cloner) dclStash(in *dclStash) (*dclStash, bool) {
|
||||
if out, exists := c.dclstash[in]; exists {
|
||||
return out, true
|
||||
}
|
||||
out := &_dclStash{}
|
||||
clone._dclStash[in] = out
|
||||
out := &dclStash{}
|
||||
c.dclstash[in] = out
|
||||
return out, false
|
||||
}
|
||||
|
||||
func (clone *_clone) objectStash(in *_objectStash) (*_objectStash, bool) {
|
||||
if out, exists := clone._objectStash[in]; exists {
|
||||
func (c *cloner) objectStash(in *objectStash) (*objectStash, bool) {
|
||||
if out, exists := c.objectstash[in]; exists {
|
||||
return out, true
|
||||
}
|
||||
out := &_objectStash{}
|
||||
clone._objectStash[in] = out
|
||||
out := &objectStash{}
|
||||
c.objectstash[in] = out
|
||||
return out, false
|
||||
}
|
||||
|
||||
func (clone *_clone) fnStash(in *_fnStash) (*_fnStash, bool) {
|
||||
if out, exists := clone._fnStash[in]; exists {
|
||||
func (c *cloner) fnStash(in *fnStash) (*fnStash, bool) {
|
||||
if out, exists := c.fnstash[in]; exists {
|
||||
return out, true
|
||||
}
|
||||
out := &_fnStash{}
|
||||
clone._fnStash[in] = out
|
||||
out := &fnStash{}
|
||||
c.fnstash[in] = out
|
||||
return out, false
|
||||
}
|
||||
|
||||
func (clone *_clone) value(in Value) Value {
|
||||
func (c *cloner) value(in Value) Value {
|
||||
out := in
|
||||
switch value := in.value.(type) {
|
||||
case *_object:
|
||||
out.value = clone.object(value)
|
||||
if value, ok := in.value.(*object); ok {
|
||||
out.value = c.object(value)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func (clone *_clone) valueArray(in []Value) []Value {
|
||||
func (c *cloner) valueArray(in []Value) []Value {
|
||||
out := make([]Value, len(in))
|
||||
for index, value := range in {
|
||||
out[index] = clone.value(value)
|
||||
out[index] = c.value(value)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func (clone *_clone) stash(in _stash) _stash {
|
||||
func (c *cloner) stash(in stasher) stasher {
|
||||
if in == 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
|
||||
|
||||
switch value := in.value.(type) {
|
||||
case Value:
|
||||
out.value = clone.value(value)
|
||||
case _propertyGetSet:
|
||||
p := _propertyGetSet{}
|
||||
out.value = c.value(value)
|
||||
case propertyGetSet:
|
||||
p := propertyGetSet{}
|
||||
if value[0] != nil {
|
||||
p[0] = clone.object(value[0])
|
||||
p[0] = c.object(value[0])
|
||||
}
|
||||
if value[1] != nil {
|
||||
p[1] = clone.object(value[1])
|
||||
p[1] = c.object(value[1])
|
||||
}
|
||||
out.value = p
|
||||
default:
|
||||
|
@ -165,8 +164,8 @@ func (clone *_clone) property(in _property) _property {
|
|||
return out
|
||||
}
|
||||
|
||||
func (clone *_clone) dclProperty(in _dclProperty) _dclProperty {
|
||||
func (c *cloner) dclProperty(in dclProperty) dclProperty {
|
||||
out := in
|
||||
out.value = clone.value(in.value)
|
||||
out.value = c.value(in.value)
|
||||
return out
|
||||
}
|
||||
|
|
9
v1/vendor/github.com/robertkrimen/otto/cmpl.go
generated
vendored
|
@ -5,14 +5,7 @@ import (
|
|||
"github.com/robertkrimen/otto/file"
|
||||
)
|
||||
|
||||
type _compiler struct {
|
||||
type compiler struct {
|
||||
file *file.File
|
||||
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"
|
||||
)
|
||||
|
||||
func (self *_runtime) cmpl_evaluate_nodeProgram(node *_nodeProgram, eval bool) Value {
|
||||
func (rt *runtime) cmplEvaluateNodeProgram(node *nodeProgram, eval bool) Value {
|
||||
if !eval {
|
||||
self.enterGlobalScope()
|
||||
defer func() {
|
||||
self.leaveScope()
|
||||
}()
|
||||
rt.enterGlobalScope()
|
||||
defer rt.leaveScope()
|
||||
}
|
||||
self.cmpl_functionDeclaration(node.functionList)
|
||||
self.cmpl_variableDeclaration(node.varList)
|
||||
self.scope.frame.file = node.file
|
||||
return self.cmpl_evaluate_nodeStatementList(node.body)
|
||||
rt.cmplFunctionDeclaration(node.functionList)
|
||||
rt.cmplVariableDeclaration(node.varList)
|
||||
rt.scope.frame.file = node.file
|
||||
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))
|
||||
// function(abc, def, ghi)
|
||||
// indexOfParameterName[0] = "abc"
|
||||
|
@ -36,28 +34,28 @@ func (self *_runtime) cmpl_call_nodeFunction(function *_object, stash *_fnStash,
|
|||
indexOfParameterName[index] = name
|
||||
}
|
||||
// strict = false
|
||||
self.scope.lexical.setValue(name, value, false)
|
||||
rt.scope.lexical.setValue(name, value, false)
|
||||
}
|
||||
|
||||
if !argumentsFound {
|
||||
arguments := self.newArgumentsObject(indexOfParameterName, stash, len(argumentList))
|
||||
arguments.defineProperty("callee", toValue_object(function), 0101, false)
|
||||
arguments := rt.newArgumentsObject(indexOfParameterName, stash, len(argumentList))
|
||||
arguments.defineProperty("callee", objectValue(function), 0o101, false)
|
||||
stash.arguments = arguments
|
||||
// strict = false
|
||||
self.scope.lexical.setValue("arguments", toValue_object(arguments), false)
|
||||
for index, _ := range argumentList {
|
||||
rt.scope.lexical.setValue("arguments", objectValue(arguments), false)
|
||||
for index := range argumentList {
|
||||
if index < len(node.parameterList) {
|
||||
continue
|
||||
}
|
||||
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)
|
||||
self.cmpl_variableDeclaration(node.varList)
|
||||
rt.cmplFunctionDeclaration(node.functionList)
|
||||
rt.cmplVariableDeclaration(node.varList)
|
||||
|
||||
result := self.cmpl_evaluate_nodeStatement(node.body)
|
||||
result := rt.cmplEvaluateNodeStatement(node.body)
|
||||
if result.kind == valueResult {
|
||||
return result
|
||||
}
|
||||
|
@ -65,16 +63,16 @@ func (self *_runtime) cmpl_call_nodeFunction(function *_object, stash *_fnStash,
|
|||
return Value{}
|
||||
}
|
||||
|
||||
func (self *_runtime) cmpl_functionDeclaration(list []*_nodeFunctionLiteral) {
|
||||
executionContext := self.scope
|
||||
func (rt *runtime) cmplFunctionDeclaration(list []*nodeFunctionLiteral) {
|
||||
executionContext := rt.scope
|
||||
eval := executionContext.eval
|
||||
stash := executionContext.variable
|
||||
|
||||
for _, function := range list {
|
||||
name := function.name
|
||||
value := self.cmpl_evaluate_nodeExpression(function)
|
||||
value := rt.cmplEvaluateNodeExpression(function)
|
||||
if !stash.hasBinding(name) {
|
||||
stash.createBinding(name, eval == true, value)
|
||||
stash.createBinding(name, eval, value)
|
||||
} else {
|
||||
// TODO 10.5.5.e
|
||||
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) {
|
||||
executionContext := self.scope
|
||||
func (rt *runtime) cmplVariableDeclaration(list []string) {
|
||||
executionContext := rt.scope
|
||||
eval := executionContext.eval
|
||||
stash := executionContext.variable
|
||||
|
||||
for _, name := range list {
|
||||
if !stash.hasBinding(name) {
|
||||
stash.createBinding(name, eval == true, Value{}) // TODO strict?
|
||||
stash.createBinding(name, eval, Value{}) // TODO strict?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
357
v1/vendor/github.com/robertkrimen/otto/cmpl_evaluate_expression.go
generated
vendored
|
@ -3,136 +3,135 @@ package otto
|
|||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"runtime"
|
||||
goruntime "runtime"
|
||||
|
||||
"github.com/robertkrimen/otto/token"
|
||||
)
|
||||
|
||||
func (self *_runtime) cmpl_evaluate_nodeExpression(node _nodeExpression) Value {
|
||||
func (rt *runtime) cmplEvaluateNodeExpression(node nodeExpression) Value {
|
||||
// Allow interpreter interruption
|
||||
// If the Interrupt channel is nil, then
|
||||
// we avoid runtime.Gosched() overhead (if any)
|
||||
// FIXME: Test this
|
||||
if self.otto.Interrupt != nil {
|
||||
runtime.Gosched()
|
||||
if rt.otto.Interrupt != nil {
|
||||
goruntime.Gosched()
|
||||
select {
|
||||
case value := <-self.otto.Interrupt:
|
||||
case value := <-rt.otto.Interrupt:
|
||||
value()
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
switch node := node.(type) {
|
||||
case *_nodeArrayLiteral:
|
||||
return self.cmpl_evaluate_nodeArrayLiteral(node)
|
||||
case *nodeArrayLiteral:
|
||||
return rt.cmplEvaluateNodeArrayLiteral(node)
|
||||
|
||||
case *_nodeAssignExpression:
|
||||
return self.cmpl_evaluate_nodeAssignExpression(node)
|
||||
case *nodeAssignExpression:
|
||||
return rt.cmplEvaluateNodeAssignExpression(node)
|
||||
|
||||
case *_nodeBinaryExpression:
|
||||
case *nodeBinaryExpression:
|
||||
if node.comparison {
|
||||
return self.cmpl_evaluate_nodeBinaryExpression_comparison(node)
|
||||
} else {
|
||||
return self.cmpl_evaluate_nodeBinaryExpression(node)
|
||||
return rt.cmplEvaluateNodeBinaryExpressionComparison(node)
|
||||
}
|
||||
return rt.cmplEvaluateNodeBinaryExpression(node)
|
||||
|
||||
case *_nodeBracketExpression:
|
||||
return self.cmpl_evaluate_nodeBracketExpression(node)
|
||||
case *nodeBracketExpression:
|
||||
return rt.cmplEvaluateNodeBracketExpression(node)
|
||||
|
||||
case *_nodeCallExpression:
|
||||
return self.cmpl_evaluate_nodeCallExpression(node, nil)
|
||||
case *nodeCallExpression:
|
||||
return rt.cmplEvaluateNodeCallExpression(node, nil)
|
||||
|
||||
case *_nodeConditionalExpression:
|
||||
return self.cmpl_evaluate_nodeConditionalExpression(node)
|
||||
case *nodeConditionalExpression:
|
||||
return rt.cmplEvaluateNodeConditionalExpression(node)
|
||||
|
||||
case *_nodeDotExpression:
|
||||
return self.cmpl_evaluate_nodeDotExpression(node)
|
||||
case *nodeDotExpression:
|
||||
return rt.cmplEvaluateNodeDotExpression(node)
|
||||
|
||||
case *_nodeFunctionLiteral:
|
||||
var local = self.scope.lexical
|
||||
case *nodeFunctionLiteral:
|
||||
local := rt.scope.lexical
|
||||
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 != "" {
|
||||
local.createBinding(node.name, false, value)
|
||||
}
|
||||
return value
|
||||
|
||||
case *_nodeIdentifier:
|
||||
case *nodeIdentifier:
|
||||
name := node.name
|
||||
// TODO Should be true or false (strictness) depending on context
|
||||
// getIdentifierReference should not return nil, but we check anyway and panic
|
||||
// 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 {
|
||||
// Should never get here!
|
||||
panic(hereBeDragons("referenceError == nil: " + name))
|
||||
}
|
||||
return toValue(reference)
|
||||
|
||||
case *_nodeLiteral:
|
||||
case *nodeLiteral:
|
||||
return node.value
|
||||
|
||||
case *_nodeNewExpression:
|
||||
return self.cmpl_evaluate_nodeNewExpression(node)
|
||||
case *nodeNewExpression:
|
||||
return rt.cmplEvaluateNodeNewExpression(node)
|
||||
|
||||
case *_nodeObjectLiteral:
|
||||
return self.cmpl_evaluate_nodeObjectLiteral(node)
|
||||
case *nodeObjectLiteral:
|
||||
return rt.cmplEvaluateNodeObjectLiteral(node)
|
||||
|
||||
case *_nodeRegExpLiteral:
|
||||
return toValue_object(self._newRegExp(node.pattern, node.flags))
|
||||
case *nodeRegExpLiteral:
|
||||
return objectValue(rt.newRegExpDirect(node.pattern, node.flags))
|
||||
|
||||
case *_nodeSequenceExpression:
|
||||
return self.cmpl_evaluate_nodeSequenceExpression(node)
|
||||
case *nodeSequenceExpression:
|
||||
return rt.cmplEvaluateNodeSequenceExpression(node)
|
||||
|
||||
case *_nodeThisExpression:
|
||||
return toValue_object(self.scope.this)
|
||||
case *nodeThisExpression:
|
||||
return objectValue(rt.scope.this)
|
||||
|
||||
case *_nodeUnaryExpression:
|
||||
return self.cmpl_evaluate_nodeUnaryExpression(node)
|
||||
case *nodeUnaryExpression:
|
||||
return rt.cmplEvaluateNodeUnaryExpression(node)
|
||||
|
||||
case *_nodeVariableExpression:
|
||||
return self.cmpl_evaluate_nodeVariableExpression(node)
|
||||
case *nodeVariableExpression:
|
||||
return rt.cmplEvaluateNodeVariableExpression(node)
|
||||
default:
|
||||
panic(fmt.Sprintf("unknown node type: %T", node))
|
||||
}
|
||||
|
||||
panic(fmt.Errorf("Here be dragons: evaluate_nodeExpression(%T)", node))
|
||||
}
|
||||
|
||||
func (self *_runtime) cmpl_evaluate_nodeArrayLiteral(node *_nodeArrayLiteral) Value {
|
||||
func (rt *runtime) cmplEvaluateNodeArrayLiteral(node *nodeArrayLiteral) Value {
|
||||
valueArray := []Value{}
|
||||
|
||||
for _, node := range node.value {
|
||||
if node == nil {
|
||||
valueArray = append(valueArray, emptyValue)
|
||||
} 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 {
|
||||
left := self.cmpl_evaluate_nodeExpression(node.left)
|
||||
right := self.cmpl_evaluate_nodeExpression(node.right)
|
||||
func (rt *runtime) cmplEvaluateNodeAssignExpression(node *nodeAssignExpression) Value {
|
||||
left := rt.cmplEvaluateNodeExpression(node.left)
|
||||
right := rt.cmplEvaluateNodeExpression(node.right)
|
||||
rightValue := right.resolve()
|
||||
|
||||
result := rightValue
|
||||
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
|
||||
}
|
||||
|
||||
func (self *_runtime) cmpl_evaluate_nodeBinaryExpression(node *_nodeBinaryExpression) Value {
|
||||
left := self.cmpl_evaluate_nodeExpression(node.left)
|
||||
func (rt *runtime) cmplEvaluateNodeBinaryExpression(node *nodeBinaryExpression) Value {
|
||||
left := rt.cmplEvaluateNodeExpression(node.left)
|
||||
leftValue := left.resolve()
|
||||
|
||||
switch node.operator {
|
||||
|
@ -141,214 +140,206 @@ func (self *_runtime) cmpl_evaluate_nodeBinaryExpression(node *_nodeBinaryExpres
|
|||
if !leftValue.bool() {
|
||||
return leftValue
|
||||
}
|
||||
right := self.cmpl_evaluate_nodeExpression(node.right)
|
||||
right := rt.cmplEvaluateNodeExpression(node.right)
|
||||
return right.resolve()
|
||||
case token.LOGICAL_OR:
|
||||
if leftValue.bool() {
|
||||
return leftValue
|
||||
}
|
||||
right := self.cmpl_evaluate_nodeExpression(node.right)
|
||||
right := rt.cmplEvaluateNodeExpression(node.right)
|
||||
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 {
|
||||
left := self.cmpl_evaluate_nodeExpression(node.left).resolve()
|
||||
right := self.cmpl_evaluate_nodeExpression(node.right).resolve()
|
||||
func (rt *runtime) cmplEvaluateNodeBinaryExpressionComparison(node *nodeBinaryExpression) Value {
|
||||
left := rt.cmplEvaluateNodeExpression(node.left).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 {
|
||||
target := self.cmpl_evaluate_nodeExpression(node.left)
|
||||
func (rt *runtime) cmplEvaluateNodeBracketExpression(node *nodeBracketExpression) Value {
|
||||
target := rt.cmplEvaluateNodeExpression(node.left)
|
||||
targetValue := target.resolve()
|
||||
member := self.cmpl_evaluate_nodeExpression(node.member)
|
||||
member := rt.cmplEvaluateNodeExpression(node.member)
|
||||
memberValue := member.resolve()
|
||||
|
||||
// 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 {
|
||||
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 {
|
||||
rt := self
|
||||
func (rt *runtime) cmplEvaluateNodeCallExpression(node *nodeCallExpression, withArgumentList []interface{}) Value {
|
||||
this := Value{}
|
||||
callee := self.cmpl_evaluate_nodeExpression(node.callee)
|
||||
callee := rt.cmplEvaluateNodeExpression(node.callee)
|
||||
|
||||
argumentList := []Value{}
|
||||
if withArgumentList != nil {
|
||||
argumentList = self.toValueArray(withArgumentList...)
|
||||
argumentList = rt.toValueArray(withArgumentList...)
|
||||
} else {
|
||||
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
|
||||
name := ""
|
||||
if rf != nil {
|
||||
if rf := callee.reference(); rf != nil {
|
||||
switch rf := rf.(type) {
|
||||
case *_propertyReference:
|
||||
case *propertyReference:
|
||||
name = rf.name
|
||||
object := rf.base
|
||||
this = toValue_object(object)
|
||||
this = objectValue(rf.base)
|
||||
eval = rf.name == "eval" // Possible direct eval
|
||||
case *_stashReference:
|
||||
case *stashReference:
|
||||
// TODO ImplicitThisValue
|
||||
name = rf.name
|
||||
eval = rf.name == "eval" // Possible direct eval
|
||||
default:
|
||||
// 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) {
|
||||
case *_nodeIdentifier:
|
||||
at = _at(callee.idx)
|
||||
case *_nodeDotExpression:
|
||||
at = _at(callee.idx)
|
||||
case *_nodeBracketExpression:
|
||||
at = _at(callee.idx)
|
||||
case *nodeIdentifier:
|
||||
atv = at(callee.idx)
|
||||
case *nodeDotExpression:
|
||||
atv = at(callee.idx)
|
||||
case *nodeBracketExpression:
|
||||
atv = at(callee.idx)
|
||||
}
|
||||
|
||||
frame := _frame{
|
||||
frm := frame{
|
||||
callee: name,
|
||||
file: self.scope.frame.file,
|
||||
file: rt.scope.frame.file,
|
||||
}
|
||||
|
||||
vl := callee.resolve()
|
||||
if !vl.IsFunction() {
|
||||
if name == "" {
|
||||
// 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 {
|
||||
test := self.cmpl_evaluate_nodeExpression(node.test)
|
||||
func (rt *runtime) cmplEvaluateNodeConditionalExpression(node *nodeConditionalExpression) Value {
|
||||
test := rt.cmplEvaluateNodeExpression(node.test)
|
||||
testValue := test.resolve()
|
||||
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 {
|
||||
target := self.cmpl_evaluate_nodeExpression(node.left)
|
||||
func (rt *runtime) cmplEvaluateNodeDotExpression(node *nodeDotExpression) Value {
|
||||
target := rt.cmplEvaluateNodeExpression(node.left)
|
||||
targetValue := target.resolve()
|
||||
// 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 {
|
||||
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 {
|
||||
rt := self
|
||||
callee := self.cmpl_evaluate_nodeExpression(node.callee)
|
||||
func (rt *runtime) cmplEvaluateNodeNewExpression(node *nodeNewExpression) Value {
|
||||
callee := rt.cmplEvaluateNodeExpression(node.callee)
|
||||
|
||||
argumentList := []Value{}
|
||||
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()
|
||||
|
||||
name := ""
|
||||
if rf != nil {
|
||||
var name string
|
||||
if rf := callee.reference(); rf != nil {
|
||||
switch rf := rf.(type) {
|
||||
case *_propertyReference:
|
||||
case *propertyReference:
|
||||
name = rf.name
|
||||
case *_stashReference:
|
||||
case *stashReference:
|
||||
name = rf.name
|
||||
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) {
|
||||
case *_nodeIdentifier:
|
||||
at = _at(callee.idx)
|
||||
case *_nodeDotExpression:
|
||||
at = _at(callee.idx)
|
||||
case *_nodeBracketExpression:
|
||||
at = _at(callee.idx)
|
||||
case *nodeIdentifier:
|
||||
atv = at(callee.idx)
|
||||
case *nodeDotExpression:
|
||||
atv = at(callee.idx)
|
||||
case *nodeBracketExpression:
|
||||
atv = at(callee.idx)
|
||||
}
|
||||
|
||||
vl := callee.resolve()
|
||||
if !vl.IsFunction() {
|
||||
if name == "" {
|
||||
// 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 {
|
||||
result := self.newObject()
|
||||
|
||||
for _, property := range node.value {
|
||||
switch property.kind {
|
||||
func (rt *runtime) cmplEvaluateNodeObjectLiteral(node *nodeObjectLiteral) Value {
|
||||
result := rt.newObject()
|
||||
for _, prop := range node.value {
|
||||
switch prop.kind {
|
||||
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":
|
||||
getter := self.newNodeFunction(property.value.(*_nodeFunctionLiteral), self.scope.lexical)
|
||||
descriptor := _property{}
|
||||
descriptor.mode = 0211
|
||||
descriptor.value = _propertyGetSet{getter, nil}
|
||||
result.defineOwnProperty(property.key, descriptor, false)
|
||||
getter := rt.newNodeFunction(prop.value.(*nodeFunctionLiteral), rt.scope.lexical)
|
||||
descriptor := property{}
|
||||
descriptor.mode = 0o211
|
||||
descriptor.value = propertyGetSet{getter, nil}
|
||||
result.defineOwnProperty(prop.key, descriptor, false)
|
||||
case "set":
|
||||
setter := self.newNodeFunction(property.value.(*_nodeFunctionLiteral), self.scope.lexical)
|
||||
descriptor := _property{}
|
||||
descriptor.mode = 0211
|
||||
descriptor.value = _propertyGetSet{nil, setter}
|
||||
result.defineOwnProperty(property.key, descriptor, false)
|
||||
setter := rt.newNodeFunction(prop.value.(*nodeFunctionLiteral), rt.scope.lexical)
|
||||
descriptor := property{}
|
||||
descriptor.mode = 0o211
|
||||
descriptor.value = propertyGetSet{nil, setter}
|
||||
result.defineOwnProperty(prop.key, descriptor, false)
|
||||
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
|
||||
for _, node := range node.sequence {
|
||||
result = self.cmpl_evaluate_nodeExpression(node)
|
||||
result = rt.cmplEvaluateNodeExpression(node)
|
||||
result = result.resolve()
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (self *_runtime) cmpl_evaluate_nodeUnaryExpression(node *_nodeUnaryExpression) Value {
|
||||
target := self.cmpl_evaluate_nodeExpression(node.operand)
|
||||
func (rt *runtime) cmplEvaluateNodeUnaryExpression(node *nodeUnaryExpression) Value {
|
||||
target := rt.cmplEvaluateNodeExpression(node.operand)
|
||||
switch node.operator {
|
||||
case token.TYPEOF, token.DELETE:
|
||||
if target.kind == valueReference && target.reference().invalid() {
|
||||
if node.operator == token.TYPEOF {
|
||||
return toValue_string("undefined")
|
||||
return stringValue("undefined")
|
||||
}
|
||||
return trueValue
|
||||
}
|
||||
|
@ -364,10 +355,10 @@ func (self *_runtime) cmpl_evaluate_nodeUnaryExpression(node *_nodeUnaryExpressi
|
|||
case token.BITWISE_NOT:
|
||||
targetValue := target.resolve()
|
||||
integerValue := toInt32(targetValue)
|
||||
return toValue_int32(^integerValue)
|
||||
return int32Value(^integerValue)
|
||||
case token.PLUS:
|
||||
targetValue := target.resolve()
|
||||
return toValue_float64(targetValue.float64())
|
||||
return float64Value(targetValue.float64())
|
||||
case token.MINUS:
|
||||
targetValue := target.resolve()
|
||||
value := targetValue.float64()
|
||||
|
@ -376,35 +367,35 @@ func (self *_runtime) cmpl_evaluate_nodeUnaryExpression(node *_nodeUnaryExpressi
|
|||
if math.Signbit(value) {
|
||||
sign = 1
|
||||
}
|
||||
return toValue_float64(math.Copysign(value, sign))
|
||||
return float64Value(math.Copysign(value, sign))
|
||||
case token.INCREMENT:
|
||||
targetValue := target.resolve()
|
||||
if node.postfix {
|
||||
// Postfix++
|
||||
oldValue := targetValue.float64()
|
||||
newValue := toValue_float64(+1 + oldValue)
|
||||
self.putValue(target.reference(), newValue)
|
||||
return toValue_float64(oldValue)
|
||||
} else {
|
||||
// ++Prefix
|
||||
newValue := toValue_float64(+1 + targetValue.float64())
|
||||
self.putValue(target.reference(), newValue)
|
||||
return newValue
|
||||
newValue := float64Value(+1 + oldValue)
|
||||
rt.putValue(target.reference(), newValue)
|
||||
return float64Value(oldValue)
|
||||
}
|
||||
|
||||
// ++Prefix
|
||||
newValue := float64Value(+1 + targetValue.float64())
|
||||
rt.putValue(target.reference(), newValue)
|
||||
return newValue
|
||||
case token.DECREMENT:
|
||||
targetValue := target.resolve()
|
||||
if node.postfix {
|
||||
// Postfix--
|
||||
oldValue := targetValue.float64()
|
||||
newValue := toValue_float64(-1 + oldValue)
|
||||
self.putValue(target.reference(), newValue)
|
||||
return toValue_float64(oldValue)
|
||||
} else {
|
||||
// --Prefix
|
||||
newValue := toValue_float64(-1 + targetValue.float64())
|
||||
self.putValue(target.reference(), newValue)
|
||||
return newValue
|
||||
newValue := float64Value(-1 + oldValue)
|
||||
rt.putValue(target.reference(), newValue)
|
||||
return float64Value(oldValue)
|
||||
}
|
||||
|
||||
// --Prefix
|
||||
newValue := float64Value(-1 + targetValue.float64())
|
||||
rt.putValue(target.reference(), newValue)
|
||||
return newValue
|
||||
case token.VOID:
|
||||
target.resolve() // FIXME Side effect?
|
||||
return Value{}
|
||||
|
@ -413,25 +404,25 @@ func (self *_runtime) cmpl_evaluate_nodeUnaryExpression(node *_nodeUnaryExpressi
|
|||
if reference == nil {
|
||||
return trueValue
|
||||
}
|
||||
return toValue_bool(target.reference().delete())
|
||||
return boolValue(target.reference().delete())
|
||||
case token.TYPEOF:
|
||||
targetValue := target.resolve()
|
||||
switch targetValue.kind {
|
||||
case valueUndefined:
|
||||
return toValue_string("undefined")
|
||||
return stringValue("undefined")
|
||||
case valueNull:
|
||||
return toValue_string("object")
|
||||
return stringValue("object")
|
||||
case valueBoolean:
|
||||
return toValue_string("boolean")
|
||||
return stringValue("boolean")
|
||||
case valueNumber:
|
||||
return toValue_string("number")
|
||||
return stringValue("number")
|
||||
case valueString:
|
||||
return toValue_string("string")
|
||||
return stringValue("string")
|
||||
case valueObject:
|
||||
if targetValue._object().isCall() {
|
||||
return toValue_string("function")
|
||||
if targetValue.object().isCall() {
|
||||
return stringValue("function")
|
||||
}
|
||||
return toValue_string("object")
|
||||
return stringValue("object")
|
||||
default:
|
||||
// FIXME ?
|
||||
}
|
||||
|
@ -440,14 +431,14 @@ func (self *_runtime) cmpl_evaluate_nodeUnaryExpression(node *_nodeUnaryExpressi
|
|||
panic(hereBeDragons())
|
||||
}
|
||||
|
||||
func (self *_runtime) cmpl_evaluate_nodeVariableExpression(node *_nodeVariableExpression) Value {
|
||||
func (rt *runtime) cmplEvaluateNodeVariableExpression(node *nodeVariableExpression) Value {
|
||||
if node.initializer != nil {
|
||||
// FIXME If reference is nil
|
||||
left := getIdentifierReference(self, self.scope.lexical, node.name, false, _at(node.idx))
|
||||
right := self.cmpl_evaluate_nodeExpression(node.initializer)
|
||||
left := getIdentifierReference(rt, rt.scope.lexical, node.name, false, at(node.idx))
|
||||
right := rt.cmplEvaluateNodeExpression(node.initializer)
|
||||
rightValue := right.resolve()
|
||||
|
||||
self.putValue(left, rightValue)
|
||||
rt.putValue(left, rightValue)
|
||||
}
|
||||
return toValue_string(node.name)
|
||||
return stringValue(node.name)
|
||||
}
|
||||
|
|
236
v1/vendor/github.com/robertkrimen/otto/cmpl_evaluate_statement.go
generated
vendored
|
@ -2,121 +2,121 @@ package otto
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
goruntime "runtime"
|
||||
|
||||
"github.com/robertkrimen/otto/token"
|
||||
)
|
||||
|
||||
func (self *_runtime) cmpl_evaluate_nodeStatement(node _nodeStatement) Value {
|
||||
func (rt *runtime) cmplEvaluateNodeStatement(node nodeStatement) Value {
|
||||
// Allow interpreter interruption
|
||||
// If the Interrupt channel is nil, then
|
||||
// we avoid runtime.Gosched() overhead (if any)
|
||||
// FIXME: Test this
|
||||
if self.otto.Interrupt != nil {
|
||||
runtime.Gosched()
|
||||
if rt.otto.Interrupt != nil {
|
||||
goruntime.Gosched()
|
||||
select {
|
||||
case value := <-self.otto.Interrupt:
|
||||
case value := <-rt.otto.Interrupt:
|
||||
value()
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
switch node := node.(type) {
|
||||
case *_nodeBlockStatement:
|
||||
labels := self.labels
|
||||
self.labels = nil
|
||||
case *nodeBlockStatement:
|
||||
labels := rt.labels
|
||||
rt.labels = nil
|
||||
|
||||
value := self.cmpl_evaluate_nodeStatementList(node.list)
|
||||
switch value.kind {
|
||||
case valueResult:
|
||||
switch value.evaluateBreak(labels) {
|
||||
case resultBreak:
|
||||
value := rt.cmplEvaluateNodeStatementList(node.list)
|
||||
if value.kind == valueResult {
|
||||
if value.evaluateBreak(labels) == resultBreak {
|
||||
return emptyValue
|
||||
}
|
||||
}
|
||||
return value
|
||||
|
||||
case *_nodeBranchStatement:
|
||||
case *nodeBranchStatement:
|
||||
target := node.label
|
||||
switch node.branch { // FIXME Maybe node.kind? node.operator?
|
||||
case token.BREAK:
|
||||
return toValue(newBreakResult(target))
|
||||
case token.CONTINUE:
|
||||
return toValue(newContinueResult(target))
|
||||
default:
|
||||
panic(fmt.Errorf("unknown node branch token %T", node))
|
||||
}
|
||||
|
||||
case *_nodeDebuggerStatement:
|
||||
if self.debugger != nil {
|
||||
self.debugger(self.otto)
|
||||
case *nodeDebuggerStatement:
|
||||
if rt.debugger != nil {
|
||||
rt.debugger(rt.otto)
|
||||
}
|
||||
return emptyValue // Nothing happens.
|
||||
|
||||
case *_nodeDoWhileStatement:
|
||||
return self.cmpl_evaluate_nodeDoWhileStatement(node)
|
||||
case *nodeDoWhileStatement:
|
||||
return rt.cmplEvaluateNodeDoWhileStatement(node)
|
||||
|
||||
case *_nodeEmptyStatement:
|
||||
case *nodeEmptyStatement:
|
||||
return emptyValue
|
||||
|
||||
case *_nodeExpressionStatement:
|
||||
return self.cmpl_evaluate_nodeExpression(node.expression)
|
||||
case *nodeExpressionStatement:
|
||||
return rt.cmplEvaluateNodeExpression(node.expression)
|
||||
|
||||
case *_nodeForInStatement:
|
||||
return self.cmpl_evaluate_nodeForInStatement(node)
|
||||
case *nodeForInStatement:
|
||||
return rt.cmplEvaluateNodeForInStatement(node)
|
||||
|
||||
case *_nodeForStatement:
|
||||
return self.cmpl_evaluate_nodeForStatement(node)
|
||||
case *nodeForStatement:
|
||||
return rt.cmplEvaluateNodeForStatement(node)
|
||||
|
||||
case *_nodeIfStatement:
|
||||
return self.cmpl_evaluate_nodeIfStatement(node)
|
||||
case *nodeIfStatement:
|
||||
return rt.cmplEvaluateNodeIfStatement(node)
|
||||
|
||||
case *_nodeLabelledStatement:
|
||||
self.labels = append(self.labels, node.label)
|
||||
case *nodeLabelledStatement:
|
||||
rt.labels = append(rt.labels, node.label)
|
||||
defer func() {
|
||||
if len(self.labels) > 0 {
|
||||
self.labels = self.labels[:len(self.labels)-1] // Pop the label
|
||||
if len(rt.labels) > 0 {
|
||||
rt.labels = rt.labels[:len(rt.labels)-1] // Pop the label
|
||||
} 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 {
|
||||
return toValue(newReturnResult(self.cmpl_evaluate_nodeExpression(node.argument).resolve()))
|
||||
return toValue(newReturnResult(rt.cmplEvaluateNodeExpression(node.argument).resolve()))
|
||||
}
|
||||
return toValue(newReturnResult(Value{}))
|
||||
|
||||
case *_nodeSwitchStatement:
|
||||
return self.cmpl_evaluate_nodeSwitchStatement(node)
|
||||
case *nodeSwitchStatement:
|
||||
return rt.cmplEvaluateNodeSwitchStatement(node)
|
||||
|
||||
case *_nodeThrowStatement:
|
||||
value := self.cmpl_evaluate_nodeExpression(node.argument).resolve()
|
||||
case *nodeThrowStatement:
|
||||
value := rt.cmplEvaluateNodeExpression(node.argument).resolve()
|
||||
panic(newException(value))
|
||||
|
||||
case *_nodeTryStatement:
|
||||
return self.cmpl_evaluate_nodeTryStatement(node)
|
||||
case *nodeTryStatement:
|
||||
return rt.cmplEvaluateNodeTryStatement(node)
|
||||
|
||||
case *_nodeVariableStatement:
|
||||
case *nodeVariableStatement:
|
||||
// Variables are already defined, this is initialization only
|
||||
for _, variable := range node.list {
|
||||
self.cmpl_evaluate_nodeVariableExpression(variable.(*_nodeVariableExpression))
|
||||
rt.cmplEvaluateNodeVariableExpression(variable.(*nodeVariableExpression))
|
||||
}
|
||||
return emptyValue
|
||||
|
||||
case *_nodeWhileStatement:
|
||||
return self.cmpl_evaluate_nodeWhileStatement(node)
|
||||
case *nodeWhileStatement:
|
||||
return rt.cmplEvaluateModeWhileStatement(node)
|
||||
|
||||
case *_nodeWithStatement:
|
||||
return self.cmpl_evaluate_nodeWithStatement(node)
|
||||
case *nodeWithStatement:
|
||||
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 (self *_runtime) cmpl_evaluate_nodeStatementList(list []_nodeStatement) Value {
|
||||
func (rt *runtime) cmplEvaluateNodeStatementList(list []nodeStatement) Value {
|
||||
var result Value
|
||||
for _, node := range list {
|
||||
value := self.cmpl_evaluate_nodeStatement(node)
|
||||
value := rt.cmplEvaluateNodeStatement(node)
|
||||
switch value.kind {
|
||||
case valueResult:
|
||||
return value
|
||||
|
@ -133,9 +133,9 @@ func (self *_runtime) cmpl_evaluate_nodeStatementList(list []_nodeStatement) Val
|
|||
return result
|
||||
}
|
||||
|
||||
func (self *_runtime) cmpl_evaluate_nodeDoWhileStatement(node *_nodeDoWhileStatement) Value {
|
||||
labels := append(self.labels, "")
|
||||
self.labels = nil
|
||||
func (rt *runtime) cmplEvaluateNodeDoWhileStatement(node *nodeDoWhileStatement) Value {
|
||||
labels := append(rt.labels, "") //nolint: gocritic
|
||||
rt.labels = nil
|
||||
|
||||
test := node.test
|
||||
|
||||
|
@ -143,7 +143,7 @@ func (self *_runtime) cmpl_evaluate_nodeDoWhileStatement(node *_nodeDoWhileState
|
|||
resultBreak:
|
||||
for {
|
||||
for _, node := range node.body {
|
||||
value := self.cmpl_evaluate_nodeStatement(node)
|
||||
value := rt.cmplEvaluateNodeStatement(node)
|
||||
switch value.kind {
|
||||
case valueResult:
|
||||
switch value.evaluateBreakContinue(labels) {
|
||||
|
@ -160,7 +160,7 @@ resultBreak:
|
|||
}
|
||||
}
|
||||
resultContinue:
|
||||
if !self.cmpl_evaluate_nodeExpression(test).resolve().bool() {
|
||||
if !rt.cmplEvaluateNodeExpression(test).resolve().bool() {
|
||||
// Stahp: do ... while (false)
|
||||
break
|
||||
}
|
||||
|
@ -168,11 +168,11 @@ resultBreak:
|
|||
return result
|
||||
}
|
||||
|
||||
func (self *_runtime) cmpl_evaluate_nodeForInStatement(node *_nodeForInStatement) Value {
|
||||
labels := append(self.labels, "")
|
||||
self.labels = nil
|
||||
func (rt *runtime) cmplEvaluateNodeForInStatement(node *nodeForInStatement) Value {
|
||||
labels := append(rt.labels, "") //nolint: gocritic
|
||||
rt.labels = nil
|
||||
|
||||
source := self.cmpl_evaluate_nodeExpression(node.source)
|
||||
source := rt.cmplEvaluateNodeExpression(node.source)
|
||||
sourceValue := source.resolve()
|
||||
|
||||
switch sourceValue.kind {
|
||||
|
@ -180,26 +180,26 @@ func (self *_runtime) cmpl_evaluate_nodeForInStatement(node *_nodeForInStatement
|
|||
return emptyValue
|
||||
}
|
||||
|
||||
sourceObject := self.toObject(sourceValue)
|
||||
sourceObject := rt.toObject(sourceValue)
|
||||
|
||||
into := node.into
|
||||
body := node.body
|
||||
|
||||
result := emptyValue
|
||||
object := sourceObject
|
||||
for object != nil {
|
||||
obj := sourceObject
|
||||
for obj != nil {
|
||||
enumerateValue := emptyValue
|
||||
object.enumerate(false, func(name string) bool {
|
||||
into := self.cmpl_evaluate_nodeExpression(into)
|
||||
obj.enumerate(false, func(name string) bool {
|
||||
into := rt.cmplEvaluateNodeExpression(into)
|
||||
// In the case of: for (var abc in def) ...
|
||||
if into.reference() == nil {
|
||||
identifier := into.string()
|
||||
// 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 {
|
||||
value := self.cmpl_evaluate_nodeStatement(node)
|
||||
value := rt.cmplEvaluateNodeStatement(node)
|
||||
switch value.kind {
|
||||
case valueResult:
|
||||
switch value.evaluateBreakContinue(labels) {
|
||||
|
@ -207,7 +207,7 @@ func (self *_runtime) cmpl_evaluate_nodeForInStatement(node *_nodeForInStatement
|
|||
enumerateValue = value
|
||||
return false
|
||||
case resultBreak:
|
||||
object = nil
|
||||
obj = nil
|
||||
return false
|
||||
case resultContinue:
|
||||
return true
|
||||
|
@ -219,10 +219,10 @@ func (self *_runtime) cmpl_evaluate_nodeForInStatement(node *_nodeForInStatement
|
|||
}
|
||||
return true
|
||||
})
|
||||
if object == nil {
|
||||
if obj == nil {
|
||||
break
|
||||
}
|
||||
object = object.prototype
|
||||
obj = obj.prototype
|
||||
if !enumerateValue.isEmpty() {
|
||||
result = enumerateValue
|
||||
}
|
||||
|
@ -230,9 +230,9 @@ func (self *_runtime) cmpl_evaluate_nodeForInStatement(node *_nodeForInStatement
|
|||
return result
|
||||
}
|
||||
|
||||
func (self *_runtime) cmpl_evaluate_nodeForStatement(node *_nodeForStatement) Value {
|
||||
labels := append(self.labels, "")
|
||||
self.labels = nil
|
||||
func (rt *runtime) cmplEvaluateNodeForStatement(node *nodeForStatement) Value {
|
||||
labels := append(rt.labels, "") //nolint: gocritic
|
||||
rt.labels = nil
|
||||
|
||||
initializer := node.initializer
|
||||
test := node.test
|
||||
|
@ -240,7 +240,7 @@ func (self *_runtime) cmpl_evaluate_nodeForStatement(node *_nodeForStatement) Va
|
|||
body := node.body
|
||||
|
||||
if initializer != nil {
|
||||
initialResult := self.cmpl_evaluate_nodeExpression(initializer)
|
||||
initialResult := rt.cmplEvaluateNodeExpression(initializer)
|
||||
initialResult.resolve() // Side-effect trigger
|
||||
}
|
||||
|
||||
|
@ -248,25 +248,25 @@ func (self *_runtime) cmpl_evaluate_nodeForStatement(node *_nodeForStatement) Va
|
|||
resultBreak:
|
||||
for {
|
||||
if test != nil {
|
||||
testResult := self.cmpl_evaluate_nodeExpression(test)
|
||||
testResult := rt.cmplEvaluateNodeExpression(test)
|
||||
testResultValue := testResult.resolve()
|
||||
if testResultValue.bool() == false {
|
||||
if !testResultValue.bool() {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// this is to prevent for cycles with no body from running forever
|
||||
if len(body) == 0 && self.otto.Interrupt != nil {
|
||||
runtime.Gosched()
|
||||
if len(body) == 0 && rt.otto.Interrupt != nil {
|
||||
goruntime.Gosched()
|
||||
select {
|
||||
case value := <-self.otto.Interrupt:
|
||||
case value := <-rt.otto.Interrupt:
|
||||
value()
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
for _, node := range body {
|
||||
value := self.cmpl_evaluate_nodeStatement(node)
|
||||
value := rt.cmplEvaluateNodeStatement(node)
|
||||
switch value.kind {
|
||||
case valueResult:
|
||||
switch value.evaluateBreakContinue(labels) {
|
||||
|
@ -284,36 +284,36 @@ resultBreak:
|
|||
}
|
||||
resultContinue:
|
||||
if update != nil {
|
||||
updateResult := self.cmpl_evaluate_nodeExpression(update)
|
||||
updateResult := rt.cmplEvaluateNodeExpression(update)
|
||||
updateResult.resolve() // Side-effect trigger
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (self *_runtime) cmpl_evaluate_nodeIfStatement(node *_nodeIfStatement) Value {
|
||||
test := self.cmpl_evaluate_nodeExpression(node.test)
|
||||
func (rt *runtime) cmplEvaluateNodeIfStatement(node *nodeIfStatement) Value {
|
||||
test := rt.cmplEvaluateNodeExpression(node.test)
|
||||
testValue := test.resolve()
|
||||
if testValue.bool() {
|
||||
return self.cmpl_evaluate_nodeStatement(node.consequent)
|
||||
return rt.cmplEvaluateNodeStatement(node.consequent)
|
||||
} else if node.alternate != nil {
|
||||
return self.cmpl_evaluate_nodeStatement(node.alternate)
|
||||
return rt.cmplEvaluateNodeStatement(node.alternate)
|
||||
}
|
||||
|
||||
return emptyValue
|
||||
}
|
||||
|
||||
func (self *_runtime) cmpl_evaluate_nodeSwitchStatement(node *_nodeSwitchStatement) Value {
|
||||
labels := append(self.labels, "")
|
||||
self.labels = nil
|
||||
func (rt *runtime) cmplEvaluateNodeSwitchStatement(node *nodeSwitchStatement) Value {
|
||||
labels := append(rt.labels, "") //nolint: gocritic
|
||||
rt.labels = nil
|
||||
|
||||
discriminantResult := self.cmpl_evaluate_nodeExpression(node.discriminant)
|
||||
target := node.default_
|
||||
discriminantResult := rt.cmplEvaluateNodeExpression(node.discriminant)
|
||||
target := node.defaultIdx
|
||||
|
||||
for index, clause := range node.body {
|
||||
test := clause.test
|
||||
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
|
||||
break
|
||||
}
|
||||
|
@ -324,7 +324,7 @@ func (self *_runtime) cmpl_evaluate_nodeSwitchStatement(node *_nodeSwitchStateme
|
|||
if target != -1 {
|
||||
for _, clause := range node.body[target:] {
|
||||
for _, statement := range clause.consequent {
|
||||
value := self.cmpl_evaluate_nodeStatement(statement)
|
||||
value := rt.cmplEvaluateNodeStatement(statement)
|
||||
switch value.kind {
|
||||
case valueResult:
|
||||
switch value.evaluateBreak(labels) {
|
||||
|
@ -344,58 +344,58 @@ func (self *_runtime) cmpl_evaluate_nodeSwitchStatement(node *_nodeSwitchStateme
|
|||
return result
|
||||
}
|
||||
|
||||
func (self *_runtime) cmpl_evaluate_nodeTryStatement(node *_nodeTryStatement) Value {
|
||||
tryCatchValue, exception := self.tryCatchEvaluate(func() Value {
|
||||
return self.cmpl_evaluate_nodeStatement(node.body)
|
||||
func (rt *runtime) cmplEvaluateNodeTryStatement(node *nodeTryStatement) Value {
|
||||
tryCatchValue, exep := rt.tryCatchEvaluate(func() Value {
|
||||
return rt.cmplEvaluateNodeStatement(node.body)
|
||||
})
|
||||
|
||||
if exception && node.catch != nil {
|
||||
outer := self.scope.lexical
|
||||
self.scope.lexical = self.newDeclarationStash(outer)
|
||||
if exep && node.catch != nil {
|
||||
outer := rt.scope.lexical
|
||||
rt.scope.lexical = rt.newDeclarationStash(outer)
|
||||
defer func() {
|
||||
self.scope.lexical = outer
|
||||
rt.scope.lexical = outer
|
||||
}()
|
||||
// TODO If necessary, convert TypeError<runtime> => TypeError
|
||||
// That, is, such errors can be thrown despite not being JavaScript "native"
|
||||
// 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.Catch
|
||||
tryCatchValue, exception = self.tryCatchEvaluate(func() Value {
|
||||
return self.cmpl_evaluate_nodeStatement(node.catch.body)
|
||||
tryCatchValue, exep = rt.tryCatchEvaluate(func() Value {
|
||||
return rt.cmplEvaluateNodeStatement(node.catch.body)
|
||||
})
|
||||
}
|
||||
|
||||
if node.finally != nil {
|
||||
finallyValue := self.cmpl_evaluate_nodeStatement(node.finally)
|
||||
finallyValue := rt.cmplEvaluateNodeStatement(node.finally)
|
||||
if finallyValue.kind == valueResult {
|
||||
return finallyValue
|
||||
}
|
||||
}
|
||||
|
||||
if exception {
|
||||
if exep {
|
||||
panic(newException(tryCatchValue))
|
||||
}
|
||||
|
||||
return tryCatchValue
|
||||
}
|
||||
|
||||
func (self *_runtime) cmpl_evaluate_nodeWhileStatement(node *_nodeWhileStatement) Value {
|
||||
func (rt *runtime) cmplEvaluateModeWhileStatement(node *nodeWhileStatement) Value {
|
||||
test := node.test
|
||||
body := node.body
|
||||
labels := append(self.labels, "")
|
||||
self.labels = nil
|
||||
labels := append(rt.labels, "") //nolint: gocritic
|
||||
rt.labels = nil
|
||||
|
||||
result := emptyValue
|
||||
resultBreakContinue:
|
||||
for {
|
||||
if !self.cmpl_evaluate_nodeExpression(test).resolve().bool() {
|
||||
if !rt.cmplEvaluateNodeExpression(test).resolve().bool() {
|
||||
// Stahp: while (false) ...
|
||||
break
|
||||
}
|
||||
for _, node := range body {
|
||||
value := self.cmpl_evaluate_nodeStatement(node)
|
||||
value := rt.cmplEvaluateNodeStatement(node)
|
||||
switch value.kind {
|
||||
case valueResult:
|
||||
switch value.evaluateBreakContinue(labels) {
|
||||
|
@ -415,14 +415,14 @@ resultBreakContinue:
|
|||
return result
|
||||
}
|
||||
|
||||
func (self *_runtime) cmpl_evaluate_nodeWithStatement(node *_nodeWithStatement) Value {
|
||||
object := self.cmpl_evaluate_nodeExpression(node.object)
|
||||
outer := self.scope.lexical
|
||||
lexical := self.newObjectStash(self.toObject(object.resolve()), outer)
|
||||
self.scope.lexical = lexical
|
||||
func (rt *runtime) cmplEvaluateNodeWithStatement(node *nodeWithStatement) Value {
|
||||
obj := rt.cmplEvaluateNodeExpression(node.object)
|
||||
outer := rt.scope.lexical
|
||||
lexical := rt.newObjectStash(rt.toObject(obj.resolve()), outer)
|
||||
rt.scope.lexical = lexical
|
||||
defer func() {
|
||||
self.scope.lexical = outer
|
||||
rt.scope.lexical = outer
|
||||
}()
|
||||
|
||||
return self.cmpl_evaluate_nodeStatement(node.body)
|
||||
return rt.cmplEvaluateNodeStatement(node.body)
|
||||
}
|
||||
|
|
606
v1/vendor/github.com/robertkrimen/otto/cmpl_parse.go
generated
vendored
|
@ -2,83 +2,84 @@ package otto
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
|
||||
"github.com/robertkrimen/otto/ast"
|
||||
"github.com/robertkrimen/otto/file"
|
||||
"github.com/robertkrimen/otto/token"
|
||||
)
|
||||
|
||||
var trueLiteral = &_nodeLiteral{value: toValue_bool(true)}
|
||||
var falseLiteral = &_nodeLiteral{value: toValue_bool(false)}
|
||||
var nullLiteral = &_nodeLiteral{value: nullValue}
|
||||
var emptyStatement = &_nodeEmptyStatement{}
|
||||
var (
|
||||
trueLiteral = &nodeLiteral{value: boolValue(true)}
|
||||
falseLiteral = &nodeLiteral{value: boolValue(false)}
|
||||
nullLiteral = &nodeLiteral{value: nullValue}
|
||||
emptyStatement = &nodeEmptyStatement{}
|
||||
)
|
||||
|
||||
func (cmpl *_compiler) parseExpression(in ast.Expression) _nodeExpression {
|
||||
if in == nil {
|
||||
func (cmpl *compiler) parseExpression(expr ast.Expression) nodeExpression {
|
||||
if expr == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
switch in := in.(type) {
|
||||
switch expr := expr.(type) {
|
||||
case *ast.ArrayLiteral:
|
||||
out := &_nodeArrayLiteral{
|
||||
value: make([]_nodeExpression, len(in.Value)),
|
||||
out := &nodeArrayLiteral{
|
||||
value: make([]nodeExpression, len(expr.Value)),
|
||||
}
|
||||
for i, value := range in.Value {
|
||||
for i, value := range expr.Value {
|
||||
out.value[i] = cmpl.parseExpression(value)
|
||||
}
|
||||
return out
|
||||
|
||||
case *ast.AssignExpression:
|
||||
return &_nodeAssignExpression{
|
||||
operator: in.Operator,
|
||||
left: cmpl.parseExpression(in.Left),
|
||||
right: cmpl.parseExpression(in.Right),
|
||||
return &nodeAssignExpression{
|
||||
operator: expr.Operator,
|
||||
left: cmpl.parseExpression(expr.Left),
|
||||
right: cmpl.parseExpression(expr.Right),
|
||||
}
|
||||
|
||||
case *ast.BinaryExpression:
|
||||
return &_nodeBinaryExpression{
|
||||
operator: in.Operator,
|
||||
left: cmpl.parseExpression(in.Left),
|
||||
right: cmpl.parseExpression(in.Right),
|
||||
comparison: in.Comparison,
|
||||
return &nodeBinaryExpression{
|
||||
operator: expr.Operator,
|
||||
left: cmpl.parseExpression(expr.Left),
|
||||
right: cmpl.parseExpression(expr.Right),
|
||||
comparison: expr.Comparison,
|
||||
}
|
||||
|
||||
case *ast.BooleanLiteral:
|
||||
if in.Value {
|
||||
if expr.Value {
|
||||
return trueLiteral
|
||||
}
|
||||
return falseLiteral
|
||||
|
||||
case *ast.BracketExpression:
|
||||
return &_nodeBracketExpression{
|
||||
idx: in.Left.Idx0(),
|
||||
left: cmpl.parseExpression(in.Left),
|
||||
member: cmpl.parseExpression(in.Member),
|
||||
return &nodeBracketExpression{
|
||||
idx: expr.Left.Idx0(),
|
||||
left: cmpl.parseExpression(expr.Left),
|
||||
member: cmpl.parseExpression(expr.Member),
|
||||
}
|
||||
|
||||
case *ast.CallExpression:
|
||||
out := &_nodeCallExpression{
|
||||
callee: cmpl.parseExpression(in.Callee),
|
||||
argumentList: make([]_nodeExpression, len(in.ArgumentList)),
|
||||
out := &nodeCallExpression{
|
||||
callee: cmpl.parseExpression(expr.Callee),
|
||||
argumentList: make([]nodeExpression, len(expr.ArgumentList)),
|
||||
}
|
||||
for i, value := range in.ArgumentList {
|
||||
for i, value := range expr.ArgumentList {
|
||||
out.argumentList[i] = cmpl.parseExpression(value)
|
||||
}
|
||||
return out
|
||||
|
||||
case *ast.ConditionalExpression:
|
||||
return &_nodeConditionalExpression{
|
||||
test: cmpl.parseExpression(in.Test),
|
||||
consequent: cmpl.parseExpression(in.Consequent),
|
||||
alternate: cmpl.parseExpression(in.Alternate),
|
||||
return &nodeConditionalExpression{
|
||||
test: cmpl.parseExpression(expr.Test),
|
||||
consequent: cmpl.parseExpression(expr.Consequent),
|
||||
alternate: cmpl.parseExpression(expr.Alternate),
|
||||
}
|
||||
|
||||
case *ast.DotExpression:
|
||||
return &_nodeDotExpression{
|
||||
idx: in.Left.Idx0(),
|
||||
left: cmpl.parseExpression(in.Left),
|
||||
identifier: in.Identifier.Name,
|
||||
return &nodeDotExpression{
|
||||
idx: expr.Left.Idx0(),
|
||||
left: cmpl.parseExpression(expr.Left),
|
||||
identifier: expr.Identifier.Name,
|
||||
}
|
||||
|
||||
case *ast.EmptyExpression:
|
||||
|
@ -86,48 +87,48 @@ func (cmpl *_compiler) parseExpression(in ast.Expression) _nodeExpression {
|
|||
|
||||
case *ast.FunctionLiteral:
|
||||
name := ""
|
||||
if in.Name != nil {
|
||||
name = in.Name.Name
|
||||
if expr.Name != nil {
|
||||
name = expr.Name.Name
|
||||
}
|
||||
out := &_nodeFunctionLiteral{
|
||||
out := &nodeFunctionLiteral{
|
||||
name: name,
|
||||
body: cmpl.parseStatement(in.Body),
|
||||
source: in.Source,
|
||||
body: cmpl.parseStatement(expr.Body),
|
||||
source: expr.Source,
|
||||
file: cmpl.file,
|
||||
}
|
||||
if in.ParameterList != nil {
|
||||
list := in.ParameterList.List
|
||||
if expr.ParameterList != nil {
|
||||
list := expr.ParameterList.List
|
||||
out.parameterList = make([]string, len(list))
|
||||
for i, value := range list {
|
||||
out.parameterList[i] = value.Name
|
||||
}
|
||||
}
|
||||
for _, value := range in.DeclarationList {
|
||||
for _, value := range expr.DeclarationList {
|
||||
switch value := value.(type) {
|
||||
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:
|
||||
for _, value := range value.List {
|
||||
out.varList = append(out.varList, value.Name)
|
||||
}
|
||||
default:
|
||||
panic(fmt.Errorf("Here be dragons: parseProgram.declaration(%T)", value))
|
||||
panic(fmt.Sprintf("parse expression unknown function declaration type %T", value))
|
||||
}
|
||||
}
|
||||
return out
|
||||
|
||||
case *ast.Identifier:
|
||||
return &_nodeIdentifier{
|
||||
idx: in.Idx,
|
||||
name: in.Name,
|
||||
return &nodeIdentifier{
|
||||
idx: expr.Idx,
|
||||
name: expr.Name,
|
||||
}
|
||||
|
||||
case *ast.NewExpression:
|
||||
out := &_nodeNewExpression{
|
||||
callee: cmpl.parseExpression(in.Callee),
|
||||
argumentList: make([]_nodeExpression, len(in.ArgumentList)),
|
||||
out := &nodeNewExpression{
|
||||
callee: cmpl.parseExpression(expr.Callee),
|
||||
argumentList: make([]nodeExpression, len(expr.ArgumentList)),
|
||||
}
|
||||
for i, value := range in.ArgumentList {
|
||||
for i, value := range expr.ArgumentList {
|
||||
out.argumentList[i] = cmpl.parseExpression(value)
|
||||
}
|
||||
return out
|
||||
|
@ -136,16 +137,16 @@ func (cmpl *_compiler) parseExpression(in ast.Expression) _nodeExpression {
|
|||
return nullLiteral
|
||||
|
||||
case *ast.NumberLiteral:
|
||||
return &_nodeLiteral{
|
||||
value: toValue(in.Value),
|
||||
return &nodeLiteral{
|
||||
value: toValue(expr.Value),
|
||||
}
|
||||
|
||||
case *ast.ObjectLiteral:
|
||||
out := &_nodeObjectLiteral{
|
||||
value: make([]_nodeProperty, len(in.Value)),
|
||||
out := &nodeObjectLiteral{
|
||||
value: make([]nodeProperty, len(expr.Value)),
|
||||
}
|
||||
for i, value := range in.Value {
|
||||
out.value[i] = _nodeProperty{
|
||||
for i, value := range expr.Value {
|
||||
out.value[i] = nodeProperty{
|
||||
key: value.Key,
|
||||
kind: value.Kind,
|
||||
value: cmpl.parseExpression(value.Value),
|
||||
|
@ -154,79 +155,79 @@ func (cmpl *_compiler) parseExpression(in ast.Expression) _nodeExpression {
|
|||
return out
|
||||
|
||||
case *ast.RegExpLiteral:
|
||||
return &_nodeRegExpLiteral{
|
||||
flags: in.Flags,
|
||||
pattern: in.Pattern,
|
||||
return &nodeRegExpLiteral{
|
||||
flags: expr.Flags,
|
||||
pattern: expr.Pattern,
|
||||
}
|
||||
|
||||
case *ast.SequenceExpression:
|
||||
out := &_nodeSequenceExpression{
|
||||
sequence: make([]_nodeExpression, len(in.Sequence)),
|
||||
out := &nodeSequenceExpression{
|
||||
sequence: make([]nodeExpression, len(expr.Sequence)),
|
||||
}
|
||||
for i, value := range in.Sequence {
|
||||
for i, value := range expr.Sequence {
|
||||
out.sequence[i] = cmpl.parseExpression(value)
|
||||
}
|
||||
return out
|
||||
|
||||
case *ast.StringLiteral:
|
||||
return &_nodeLiteral{
|
||||
value: toValue_string(in.Value),
|
||||
return &nodeLiteral{
|
||||
value: stringValue(expr.Value),
|
||||
}
|
||||
|
||||
case *ast.ThisExpression:
|
||||
return &_nodeThisExpression{}
|
||||
return &nodeThisExpression{}
|
||||
|
||||
case *ast.UnaryExpression:
|
||||
return &_nodeUnaryExpression{
|
||||
operator: in.Operator,
|
||||
operand: cmpl.parseExpression(in.Operand),
|
||||
postfix: in.Postfix,
|
||||
return &nodeUnaryExpression{
|
||||
operator: expr.Operator,
|
||||
operand: cmpl.parseExpression(expr.Operand),
|
||||
postfix: expr.Postfix,
|
||||
}
|
||||
|
||||
case *ast.VariableExpression:
|
||||
return &_nodeVariableExpression{
|
||||
idx: in.Idx0(),
|
||||
name: in.Name,
|
||||
initializer: cmpl.parseExpression(in.Initializer),
|
||||
return &nodeVariableExpression{
|
||||
idx: expr.Idx0(),
|
||||
name: expr.Name,
|
||||
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(in ast.Statement) _nodeStatement {
|
||||
if in == nil {
|
||||
func (cmpl *compiler) parseStatement(stmt ast.Statement) nodeStatement {
|
||||
if stmt == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
switch in := in.(type) {
|
||||
switch stmt := stmt.(type) {
|
||||
case *ast.BlockStatement:
|
||||
out := &_nodeBlockStatement{
|
||||
list: make([]_nodeStatement, len(in.List)),
|
||||
out := &nodeBlockStatement{
|
||||
list: make([]nodeStatement, len(stmt.List)),
|
||||
}
|
||||
for i, value := range in.List {
|
||||
for i, value := range stmt.List {
|
||||
out.list[i] = cmpl.parseStatement(value)
|
||||
}
|
||||
return out
|
||||
|
||||
case *ast.BranchStatement:
|
||||
out := &_nodeBranchStatement{
|
||||
branch: in.Token,
|
||||
out := &nodeBranchStatement{
|
||||
branch: stmt.Token,
|
||||
}
|
||||
if in.Label != nil {
|
||||
out.label = in.Label.Name
|
||||
if stmt.Label != nil {
|
||||
out.label = stmt.Label.Name
|
||||
}
|
||||
return out
|
||||
|
||||
case *ast.DebuggerStatement:
|
||||
return &_nodeDebuggerStatement{}
|
||||
return &nodeDebuggerStatement{}
|
||||
|
||||
case *ast.DoWhileStatement:
|
||||
out := &_nodeDoWhileStatement{
|
||||
test: cmpl.parseExpression(in.Test),
|
||||
out := &nodeDoWhileStatement{
|
||||
test: cmpl.parseExpression(stmt.Test),
|
||||
}
|
||||
body := cmpl.parseStatement(in.Body)
|
||||
if block, ok := body.(*_nodeBlockStatement); ok {
|
||||
body := cmpl.parseStatement(stmt.Body)
|
||||
if block, ok := body.(*nodeBlockStatement); ok {
|
||||
out.body = block.list
|
||||
} else {
|
||||
out.body = append(out.body, body)
|
||||
|
@ -237,17 +238,17 @@ func (cmpl *_compiler) parseStatement(in ast.Statement) _nodeStatement {
|
|||
return emptyStatement
|
||||
|
||||
case *ast.ExpressionStatement:
|
||||
return &_nodeExpressionStatement{
|
||||
expression: cmpl.parseExpression(in.Expression),
|
||||
return &nodeExpressionStatement{
|
||||
expression: cmpl.parseExpression(stmt.Expression),
|
||||
}
|
||||
|
||||
case *ast.ForInStatement:
|
||||
out := &_nodeForInStatement{
|
||||
into: cmpl.parseExpression(in.Into),
|
||||
source: cmpl.parseExpression(in.Source),
|
||||
out := &nodeForInStatement{
|
||||
into: cmpl.parseExpression(stmt.Into),
|
||||
source: cmpl.parseExpression(stmt.Source),
|
||||
}
|
||||
body := cmpl.parseStatement(in.Body)
|
||||
if block, ok := body.(*_nodeBlockStatement); ok {
|
||||
body := cmpl.parseStatement(stmt.Body)
|
||||
if block, ok := body.(*nodeBlockStatement); ok {
|
||||
out.body = block.list
|
||||
} else {
|
||||
out.body = append(out.body, body)
|
||||
|
@ -255,13 +256,13 @@ func (cmpl *_compiler) parseStatement(in ast.Statement) _nodeStatement {
|
|||
return out
|
||||
|
||||
case *ast.ForStatement:
|
||||
out := &_nodeForStatement{
|
||||
initializer: cmpl.parseExpression(in.Initializer),
|
||||
update: cmpl.parseExpression(in.Update),
|
||||
test: cmpl.parseExpression(in.Test),
|
||||
out := &nodeForStatement{
|
||||
initializer: cmpl.parseExpression(stmt.Initializer),
|
||||
update: cmpl.parseExpression(stmt.Update),
|
||||
test: cmpl.parseExpression(stmt.Test),
|
||||
}
|
||||
body := cmpl.parseStatement(in.Body)
|
||||
if block, ok := body.(*_nodeBlockStatement); ok {
|
||||
body := cmpl.parseStatement(stmt.Body)
|
||||
if block, ok := body.(*nodeBlockStatement); ok {
|
||||
out.body = block.list
|
||||
} else {
|
||||
out.body = append(out.body, body)
|
||||
|
@ -272,33 +273,33 @@ func (cmpl *_compiler) parseStatement(in ast.Statement) _nodeStatement {
|
|||
return emptyStatement
|
||||
|
||||
case *ast.IfStatement:
|
||||
return &_nodeIfStatement{
|
||||
test: cmpl.parseExpression(in.Test),
|
||||
consequent: cmpl.parseStatement(in.Consequent),
|
||||
alternate: cmpl.parseStatement(in.Alternate),
|
||||
return &nodeIfStatement{
|
||||
test: cmpl.parseExpression(stmt.Test),
|
||||
consequent: cmpl.parseStatement(stmt.Consequent),
|
||||
alternate: cmpl.parseStatement(stmt.Alternate),
|
||||
}
|
||||
|
||||
case *ast.LabelledStatement:
|
||||
return &_nodeLabelledStatement{
|
||||
label: in.Label.Name,
|
||||
statement: cmpl.parseStatement(in.Statement),
|
||||
return &nodeLabelledStatement{
|
||||
label: stmt.Label.Name,
|
||||
statement: cmpl.parseStatement(stmt.Statement),
|
||||
}
|
||||
|
||||
case *ast.ReturnStatement:
|
||||
return &_nodeReturnStatement{
|
||||
argument: cmpl.parseExpression(in.Argument),
|
||||
return &nodeReturnStatement{
|
||||
argument: cmpl.parseExpression(stmt.Argument),
|
||||
}
|
||||
|
||||
case *ast.SwitchStatement:
|
||||
out := &_nodeSwitchStatement{
|
||||
discriminant: cmpl.parseExpression(in.Discriminant),
|
||||
default_: in.Default,
|
||||
body: make([]*_nodeCaseStatement, len(in.Body)),
|
||||
out := &nodeSwitchStatement{
|
||||
discriminant: cmpl.parseExpression(stmt.Discriminant),
|
||||
defaultIdx: stmt.Default,
|
||||
body: make([]*nodeCaseStatement, len(stmt.Body)),
|
||||
}
|
||||
for i, clause := range in.Body {
|
||||
out.body[i] = &_nodeCaseStatement{
|
||||
for i, clause := range stmt.Body {
|
||||
out.body[i] = &nodeCaseStatement{
|
||||
test: cmpl.parseExpression(clause.Test),
|
||||
consequent: make([]_nodeStatement, len(clause.Consequent)),
|
||||
consequent: make([]nodeStatement, len(clause.Consequent)),
|
||||
}
|
||||
for j, value := range clause.Consequent {
|
||||
out.body[i].consequent[j] = cmpl.parseStatement(value)
|
||||
|
@ -307,38 +308,38 @@ func (cmpl *_compiler) parseStatement(in ast.Statement) _nodeStatement {
|
|||
return out
|
||||
|
||||
case *ast.ThrowStatement:
|
||||
return &_nodeThrowStatement{
|
||||
argument: cmpl.parseExpression(in.Argument),
|
||||
return &nodeThrowStatement{
|
||||
argument: cmpl.parseExpression(stmt.Argument),
|
||||
}
|
||||
|
||||
case *ast.TryStatement:
|
||||
out := &_nodeTryStatement{
|
||||
body: cmpl.parseStatement(in.Body),
|
||||
finally: cmpl.parseStatement(in.Finally),
|
||||
out := &nodeTryStatement{
|
||||
body: cmpl.parseStatement(stmt.Body),
|
||||
finally: cmpl.parseStatement(stmt.Finally),
|
||||
}
|
||||
if in.Catch != nil {
|
||||
out.catch = &_nodeCatchStatement{
|
||||
parameter: in.Catch.Parameter.Name,
|
||||
body: cmpl.parseStatement(in.Catch.Body),
|
||||
if stmt.Catch != nil {
|
||||
out.catch = &nodeCatchStatement{
|
||||
parameter: stmt.Catch.Parameter.Name,
|
||||
body: cmpl.parseStatement(stmt.Catch.Body),
|
||||
}
|
||||
}
|
||||
return out
|
||||
|
||||
case *ast.VariableStatement:
|
||||
out := &_nodeVariableStatement{
|
||||
list: make([]_nodeExpression, len(in.List)),
|
||||
out := &nodeVariableStatement{
|
||||
list: make([]nodeExpression, len(stmt.List)),
|
||||
}
|
||||
for i, value := range in.List {
|
||||
for i, value := range stmt.List {
|
||||
out.list[i] = cmpl.parseExpression(value)
|
||||
}
|
||||
return out
|
||||
|
||||
case *ast.WhileStatement:
|
||||
out := &_nodeWhileStatement{
|
||||
test: cmpl.parseExpression(in.Test),
|
||||
out := &nodeWhileStatement{
|
||||
test: cmpl.parseExpression(stmt.Test),
|
||||
}
|
||||
body := cmpl.parseStatement(in.Body)
|
||||
if block, ok := body.(*_nodeBlockStatement); ok {
|
||||
body := cmpl.parseStatement(stmt.Body)
|
||||
if block, ok := body.(*nodeBlockStatement); ok {
|
||||
out.body = block.list
|
||||
} else {
|
||||
out.body = append(out.body, body)
|
||||
|
@ -346,307 +347,298 @@ func (cmpl *_compiler) parseStatement(in ast.Statement) _nodeStatement {
|
|||
return out
|
||||
|
||||
case *ast.WithStatement:
|
||||
return &_nodeWithStatement{
|
||||
object: cmpl.parseExpression(in.Object),
|
||||
body: cmpl.parseStatement(in.Body),
|
||||
return &nodeWithStatement{
|
||||
object: cmpl.parseExpression(stmt.Object),
|
||||
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 cmpl_parse(in *ast.Program) *_nodeProgram {
|
||||
cmpl := _compiler{
|
||||
func cmplParse(in *ast.Program) *nodeProgram {
|
||||
cmpl := compiler{
|
||||
program: in,
|
||||
}
|
||||
if cmpl.program != nil {
|
||||
cmpl.file = cmpl.program.File
|
||||
}
|
||||
|
||||
return cmpl.parse()
|
||||
}
|
||||
|
||||
func (cmpl *_compiler) _parse(in *ast.Program) *_nodeProgram {
|
||||
out := &_nodeProgram{
|
||||
body: make([]_nodeStatement, len(in.Body)),
|
||||
file: in.File,
|
||||
func (cmpl *compiler) parse() *nodeProgram {
|
||||
out := &nodeProgram{
|
||||
body: make([]nodeStatement, len(cmpl.program.Body)),
|
||||
file: cmpl.program.File,
|
||||
}
|
||||
for i, value := range in.Body {
|
||||
for i, value := range cmpl.program.Body {
|
||||
out.body[i] = cmpl.parseStatement(value)
|
||||
}
|
||||
for _, value := range in.DeclarationList {
|
||||
for _, value := range cmpl.program.DeclarationList {
|
||||
switch value := value.(type) {
|
||||
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:
|
||||
for _, value := range value.List {
|
||||
out.varList = append(out.varList, value.Name)
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
type _nodeProgram struct {
|
||||
body []_nodeStatement
|
||||
type nodeProgram struct {
|
||||
body []nodeStatement
|
||||
|
||||
varList []string
|
||||
functionList []*_nodeFunctionLiteral
|
||||
|
||||
variableList []_nodeDeclaration
|
||||
functionList []*nodeFunctionLiteral
|
||||
|
||||
file *file.File
|
||||
}
|
||||
|
||||
type _nodeDeclaration struct {
|
||||
name string
|
||||
definition _node
|
||||
}
|
||||
|
||||
type _node interface {
|
||||
}
|
||||
type node interface{}
|
||||
|
||||
type (
|
||||
_nodeExpression interface {
|
||||
_node
|
||||
_expressionNode()
|
||||
nodeExpression interface {
|
||||
node
|
||||
expressionNode()
|
||||
}
|
||||
|
||||
_nodeArrayLiteral struct {
|
||||
value []_nodeExpression
|
||||
nodeArrayLiteral struct {
|
||||
value []nodeExpression
|
||||
}
|
||||
|
||||
_nodeAssignExpression struct {
|
||||
nodeAssignExpression struct {
|
||||
operator token.Token
|
||||
left _nodeExpression
|
||||
right _nodeExpression
|
||||
left nodeExpression
|
||||
right nodeExpression
|
||||
}
|
||||
|
||||
_nodeBinaryExpression struct {
|
||||
nodeBinaryExpression struct {
|
||||
operator token.Token
|
||||
left _nodeExpression
|
||||
right _nodeExpression
|
||||
left nodeExpression
|
||||
right nodeExpression
|
||||
comparison bool
|
||||
}
|
||||
|
||||
_nodeBracketExpression struct {
|
||||
nodeBracketExpression struct {
|
||||
idx file.Idx
|
||||
left _nodeExpression
|
||||
member _nodeExpression
|
||||
left nodeExpression
|
||||
member nodeExpression
|
||||
}
|
||||
|
||||
_nodeCallExpression struct {
|
||||
callee _nodeExpression
|
||||
argumentList []_nodeExpression
|
||||
nodeCallExpression struct {
|
||||
callee nodeExpression
|
||||
argumentList []nodeExpression
|
||||
}
|
||||
|
||||
_nodeConditionalExpression struct {
|
||||
test _nodeExpression
|
||||
consequent _nodeExpression
|
||||
alternate _nodeExpression
|
||||
nodeConditionalExpression struct {
|
||||
test nodeExpression
|
||||
consequent nodeExpression
|
||||
alternate nodeExpression
|
||||
}
|
||||
|
||||
_nodeDotExpression struct {
|
||||
nodeDotExpression struct {
|
||||
idx file.Idx
|
||||
left _nodeExpression
|
||||
left nodeExpression
|
||||
identifier string
|
||||
}
|
||||
|
||||
_nodeFunctionLiteral struct {
|
||||
nodeFunctionLiteral struct {
|
||||
name string
|
||||
body _nodeStatement
|
||||
body nodeStatement
|
||||
source string
|
||||
parameterList []string
|
||||
varList []string
|
||||
functionList []*_nodeFunctionLiteral
|
||||
functionList []*nodeFunctionLiteral
|
||||
file *file.File
|
||||
}
|
||||
|
||||
_nodeIdentifier struct {
|
||||
nodeIdentifier struct {
|
||||
idx file.Idx
|
||||
name string
|
||||
}
|
||||
|
||||
_nodeLiteral struct {
|
||||
nodeLiteral struct {
|
||||
value Value
|
||||
}
|
||||
|
||||
_nodeNewExpression struct {
|
||||
callee _nodeExpression
|
||||
argumentList []_nodeExpression
|
||||
nodeNewExpression struct {
|
||||
callee nodeExpression
|
||||
argumentList []nodeExpression
|
||||
}
|
||||
|
||||
_nodeObjectLiteral struct {
|
||||
value []_nodeProperty
|
||||
nodeObjectLiteral struct {
|
||||
value []nodeProperty
|
||||
}
|
||||
|
||||
_nodeProperty struct {
|
||||
nodeProperty struct {
|
||||
key string
|
||||
kind string
|
||||
value _nodeExpression
|
||||
value nodeExpression
|
||||
}
|
||||
|
||||
_nodeRegExpLiteral struct {
|
||||
nodeRegExpLiteral struct {
|
||||
flags string
|
||||
pattern string // Value?
|
||||
regexp *regexp.Regexp
|
||||
}
|
||||
|
||||
_nodeSequenceExpression struct {
|
||||
sequence []_nodeExpression
|
||||
nodeSequenceExpression struct {
|
||||
sequence []nodeExpression
|
||||
}
|
||||
|
||||
_nodeThisExpression struct {
|
||||
}
|
||||
nodeThisExpression struct{}
|
||||
|
||||
_nodeUnaryExpression struct {
|
||||
nodeUnaryExpression struct {
|
||||
operator token.Token
|
||||
operand _nodeExpression
|
||||
operand nodeExpression
|
||||
postfix bool
|
||||
}
|
||||
|
||||
_nodeVariableExpression struct {
|
||||
nodeVariableExpression struct {
|
||||
idx file.Idx
|
||||
name string
|
||||
initializer _nodeExpression
|
||||
initializer nodeExpression
|
||||
}
|
||||
)
|
||||
|
||||
type (
|
||||
_nodeStatement interface {
|
||||
_node
|
||||
_statementNode()
|
||||
nodeStatement interface {
|
||||
node
|
||||
statementNode()
|
||||
}
|
||||
|
||||
_nodeBlockStatement struct {
|
||||
list []_nodeStatement
|
||||
nodeBlockStatement struct {
|
||||
list []nodeStatement
|
||||
}
|
||||
|
||||
_nodeBranchStatement struct {
|
||||
nodeBranchStatement struct {
|
||||
branch token.Token
|
||||
label string
|
||||
}
|
||||
|
||||
_nodeCaseStatement struct {
|
||||
test _nodeExpression
|
||||
consequent []_nodeStatement
|
||||
nodeCaseStatement struct {
|
||||
test nodeExpression
|
||||
consequent []nodeStatement
|
||||
}
|
||||
|
||||
_nodeCatchStatement struct {
|
||||
nodeCatchStatement struct {
|
||||
parameter string
|
||||
body _nodeStatement
|
||||
body nodeStatement
|
||||
}
|
||||
|
||||
_nodeDebuggerStatement struct {
|
||||
nodeDebuggerStatement struct{}
|
||||
|
||||
nodeDoWhileStatement struct {
|
||||
test nodeExpression
|
||||
body []nodeStatement
|
||||
}
|
||||
|
||||
_nodeDoWhileStatement struct {
|
||||
test _nodeExpression
|
||||
body []_nodeStatement
|
||||
nodeEmptyStatement struct{}
|
||||
|
||||
nodeExpressionStatement struct {
|
||||
expression nodeExpression
|
||||
}
|
||||
|
||||
_nodeEmptyStatement struct {
|
||||
nodeForInStatement struct {
|
||||
into nodeExpression
|
||||
source nodeExpression
|
||||
body []nodeStatement
|
||||
}
|
||||
|
||||
_nodeExpressionStatement struct {
|
||||
expression _nodeExpression
|
||||
nodeForStatement struct {
|
||||
initializer nodeExpression
|
||||
update nodeExpression
|
||||
test nodeExpression
|
||||
body []nodeStatement
|
||||
}
|
||||
|
||||
_nodeForInStatement struct {
|
||||
into _nodeExpression
|
||||
source _nodeExpression
|
||||
body []_nodeStatement
|
||||
nodeIfStatement struct {
|
||||
test nodeExpression
|
||||
consequent nodeStatement
|
||||
alternate nodeStatement
|
||||
}
|
||||
|
||||
_nodeForStatement struct {
|
||||
initializer _nodeExpression
|
||||
update _nodeExpression
|
||||
test _nodeExpression
|
||||
body []_nodeStatement
|
||||
}
|
||||
|
||||
_nodeIfStatement struct {
|
||||
test _nodeExpression
|
||||
consequent _nodeStatement
|
||||
alternate _nodeStatement
|
||||
}
|
||||
|
||||
_nodeLabelledStatement struct {
|
||||
nodeLabelledStatement struct {
|
||||
label string
|
||||
statement _nodeStatement
|
||||
statement nodeStatement
|
||||
}
|
||||
|
||||
_nodeReturnStatement struct {
|
||||
argument _nodeExpression
|
||||
nodeReturnStatement struct {
|
||||
argument nodeExpression
|
||||
}
|
||||
|
||||
_nodeSwitchStatement struct {
|
||||
discriminant _nodeExpression
|
||||
default_ int
|
||||
body []*_nodeCaseStatement
|
||||
nodeSwitchStatement struct {
|
||||
discriminant nodeExpression
|
||||
defaultIdx int
|
||||
body []*nodeCaseStatement
|
||||
}
|
||||
|
||||
_nodeThrowStatement struct {
|
||||
argument _nodeExpression
|
||||
nodeThrowStatement struct {
|
||||
argument nodeExpression
|
||||
}
|
||||
|
||||
_nodeTryStatement struct {
|
||||
body _nodeStatement
|
||||
catch *_nodeCatchStatement
|
||||
finally _nodeStatement
|
||||
nodeTryStatement struct {
|
||||
body nodeStatement
|
||||
catch *nodeCatchStatement
|
||||
finally nodeStatement
|
||||
}
|
||||
|
||||
_nodeVariableStatement struct {
|
||||
list []_nodeExpression
|
||||
nodeVariableStatement struct {
|
||||
list []nodeExpression
|
||||
}
|
||||
|
||||
_nodeWhileStatement struct {
|
||||
test _nodeExpression
|
||||
body []_nodeStatement
|
||||
nodeWhileStatement struct {
|
||||
test nodeExpression
|
||||
body []nodeStatement
|
||||
}
|
||||
|
||||
_nodeWithStatement struct {
|
||||
object _nodeExpression
|
||||
body _nodeStatement
|
||||
nodeWithStatement struct {
|
||||
object nodeExpression
|
||||
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() {}
|
||||
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
|
||||
|
||||
// _statementNode
|
||||
|
||||
func (*_nodeBlockStatement) _statementNode() {}
|
||||
func (*_nodeBranchStatement) _statementNode() {}
|
||||
func (*_nodeCaseStatement) _statementNode() {}
|
||||
func (*_nodeCatchStatement) _statementNode() {}
|
||||
func (*_nodeDebuggerStatement) _statementNode() {}
|
||||
func (*_nodeDoWhileStatement) _statementNode() {}
|
||||
func (*_nodeEmptyStatement) _statementNode() {}
|
||||
func (*_nodeExpressionStatement) _statementNode() {}
|
||||
func (*_nodeForInStatement) _statementNode() {}
|
||||
func (*_nodeForStatement) _statementNode() {}
|
||||
func (*_nodeIfStatement) _statementNode() {}
|
||||
func (*_nodeLabelledStatement) _statementNode() {}
|
||||
func (*_nodeReturnStatement) _statementNode() {}
|
||||
func (*_nodeSwitchStatement) _statementNode() {}
|
||||
func (*_nodeThrowStatement) _statementNode() {}
|
||||
func (*_nodeTryStatement) _statementNode() {}
|
||||
func (*_nodeVariableStatement) _statementNode() {}
|
||||
func (*_nodeWhileStatement) _statementNode() {}
|
||||
func (*_nodeWithStatement) _statementNode() {}
|
||||
func (*nodeBlockStatement) statementNode() {}
|
||||
func (*nodeBranchStatement) statementNode() {}
|
||||
func (*nodeCaseStatement) statementNode() {}
|
||||
func (*nodeCatchStatement) statementNode() {}
|
||||
func (*nodeDebuggerStatement) statementNode() {}
|
||||
func (*nodeDoWhileStatement) statementNode() {}
|
||||
func (*nodeEmptyStatement) statementNode() {}
|
||||
func (*nodeExpressionStatement) statementNode() {}
|
||||
func (*nodeForInStatement) statementNode() {}
|
||||
func (*nodeForStatement) statementNode() {}
|
||||
func (*nodeIfStatement) statementNode() {}
|
||||
func (*nodeLabelledStatement) statementNode() {}
|
||||
func (*nodeReturnStatement) statementNode() {}
|
||||
func (*nodeSwitchStatement) statementNode() {}
|
||||
func (*nodeThrowStatement) statementNode() {}
|
||||
func (*nodeTryStatement) statementNode() {}
|
||||
func (*nodeVariableStatement) 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, " ")
|
||||
}
|
||||
|
||||
func builtinConsole_log(call FunctionCall) Value {
|
||||
func builtinConsoleLog(call FunctionCall) Value {
|
||||
fmt.Fprintln(os.Stdout, formatForConsole(call.ArgumentList))
|
||||
return Value{}
|
||||
}
|
||||
|
||||
func builtinConsole_error(call FunctionCall) Value {
|
||||
func builtinConsoleError(call FunctionCall) Value {
|
||||
fmt.Fprintln(os.Stdout, formatForConsole(call.ArgumentList))
|
||||
return Value{}
|
||||
}
|
||||
|
||||
// Nothing happens.
|
||||
func builtinConsole_dir(call FunctionCall) Value {
|
||||
func builtinConsoleDir(call FunctionCall) Value {
|
||||
return Value{}
|
||||
}
|
||||
|
||||
func builtinConsole_time(call FunctionCall) Value {
|
||||
func builtinConsoleTime(call FunctionCall) Value {
|
||||
return Value{}
|
||||
}
|
||||
|
||||
func builtinConsole_timeEnd(call FunctionCall) Value {
|
||||
func builtinConsoleTimeEnd(call FunctionCall) Value {
|
||||
return Value{}
|
||||
}
|
||||
|
||||
func builtinConsole_trace(call FunctionCall) Value {
|
||||
func builtinConsoleTrace(call FunctionCall) Value {
|
||||
return Value{}
|
||||
}
|
||||
|
||||
func builtinConsole_assert(call FunctionCall) Value {
|
||||
func builtinConsoleAssert(call FunctionCall) 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 (
|
||||
// Common classes.
|
||||
classString = "String"
|
||||
classGoArray = "GoArray"
|
||||
classGoSlice = "GoSlice"
|
||||
classNumber = "Number"
|
||||
classDate = "Date"
|
||||
classArray = "Array"
|
||||
classFunction = "Function"
|
||||
classObject = "Object"
|
||||
classRegExp = "RegExp"
|
||||
classBoolean = "Boolean"
|
||||
classError = "Error"
|
||||
classStringName = "String"
|
||||
classGoArrayName = "GoArray"
|
||||
classGoSliceName = "GoSlice"
|
||||
classNumberName = "Number"
|
||||
classDateName = "Date"
|
||||
classArrayName = "Array"
|
||||
classFunctionName = "Function"
|
||||
classObjectName = "Object"
|
||||
classRegExpName = "RegExp"
|
||||
classBooleanName = "Boolean"
|
||||
classMathName = "Math"
|
||||
classJSONName = "JSON"
|
||||
|
||||
// Error classes.
|
||||
classErrorName = "Error"
|
||||
classEvalErrorName = "EvalError"
|
||||
classTypeErrorName = "TypeError"
|
||||
classRangeErrorName = "RangeError"
|
||||
classReferenceErrorName = "ReferenceError"
|
||||
classSyntaxErrorName = "SyntaxError"
|
||||
classURIErrorName = "URIError"
|
||||
|
||||
// Common properties.
|
||||
propertyName = "name"
|
||||
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) {
|
||||
dbgr.SetOutput(&buffer)
|
||||
})
|
||||
|
||||
*/
|
||||
package dbg
|
||||
|
||||
|
@ -63,7 +62,7 @@ import (
|
|||
"log"
|
||||
"os"
|
||||
"regexp"
|
||||
"runtime"
|
||||
goruntime "runtime"
|
||||
"strings"
|
||||
"unicode"
|
||||
)
|
||||
|
@ -130,14 +129,13 @@ func parseFormat(format string) (frmt _frmt) {
|
|||
}
|
||||
|
||||
type Dbgr struct {
|
||||
emit _emit
|
||||
emit emit
|
||||
}
|
||||
|
||||
type DbgFunction func(values ...interface{})
|
||||
|
||||
func NewDbgr() *Dbgr {
|
||||
self := &Dbgr{}
|
||||
return self
|
||||
return &Dbgr{}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -153,7 +151,6 @@ they output to by passing in an (optional) customization function:
|
|||
dbg, dbgf := Dbg.New(func(dbgr *Dbgr) {
|
||||
dbgr.SetOutput(os.Stderr)
|
||||
})
|
||||
|
||||
*/
|
||||
func New(options ...interface{}) (dbg DbgFunction, dbgf DbgFunction) {
|
||||
dbgr := NewDbgr()
|
||||
|
@ -165,26 +162,25 @@ func New(options ...interface{}) (dbg DbgFunction, dbgf DbgFunction) {
|
|||
return dbgr.DbgDbgf()
|
||||
}
|
||||
|
||||
func (self Dbgr) Dbg(values ...interface{}) {
|
||||
self.getEmit().emit(_frmt{}, "", values...)
|
||||
func (d Dbgr) Dbg(values ...interface{}) {
|
||||
d.getEmit().emit(_frmt{}, "", values...)
|
||||
}
|
||||
|
||||
func (self Dbgr) Dbgf(values ...interface{}) {
|
||||
self.dbgf(values...)
|
||||
func (d Dbgr) Dbgf(values ...interface{}) {
|
||||
d.dbgf(values...)
|
||||
}
|
||||
|
||||
func (self Dbgr) DbgDbgf() (dbg DbgFunction, dbgf DbgFunction) {
|
||||
func (d Dbgr) DbgDbgf() (dbg DbgFunction, dbgf DbgFunction) {
|
||||
dbg = func(vl ...interface{}) {
|
||||
self.Dbg(vl...)
|
||||
d.Dbg(vl...)
|
||||
}
|
||||
dbgf = func(vl ...interface{}) {
|
||||
self.dbgf(vl...)
|
||||
d.dbgf(vl...)
|
||||
}
|
||||
return dbg, dbgf // Redundant, but...
|
||||
}
|
||||
|
||||
func (self Dbgr) dbgf(values ...interface{}) {
|
||||
|
||||
func (d Dbgr) dbgf(values ...interface{}) {
|
||||
var frmt _frmt
|
||||
if len(values) > 0 {
|
||||
tmp := fmt.Sprint(values[0])
|
||||
|
@ -192,7 +188,7 @@ func (self Dbgr) dbgf(values ...interface{}) {
|
|||
values = values[1:]
|
||||
}
|
||||
|
||||
buffer_f := bytes.Buffer{}
|
||||
buf := bytes.Buffer{}
|
||||
format := frmt.format
|
||||
end := len(format)
|
||||
for at := 0; at < end; {
|
||||
|
@ -201,7 +197,7 @@ func (self Dbgr) dbgf(values ...interface{}) {
|
|||
at++
|
||||
}
|
||||
if at > last {
|
||||
buffer_f.WriteString(format[last:at])
|
||||
buf.WriteString(format[last:at])
|
||||
}
|
||||
if at >= end {
|
||||
break
|
||||
|
@ -211,72 +207,70 @@ func (self Dbgr) dbgf(values ...interface{}) {
|
|||
// format[at] == ?
|
||||
if format[at] == '@' {
|
||||
depth := 2
|
||||
pc, _, _, _ := runtime.Caller(depth)
|
||||
name := runtime.FuncForPC(pc).Name()
|
||||
buffer_f.WriteString(name)
|
||||
pc, _, _, _ := goruntime.Caller(depth)
|
||||
name := goruntime.FuncForPC(pc).Name()
|
||||
buf.WriteString(name)
|
||||
} else {
|
||||
buffer_f.WriteString(format[at-1 : at+1])
|
||||
buf.WriteString(format[at-1 : at+1])
|
||||
}
|
||||
at++
|
||||
}
|
||||
|
||||
//values_f := append([]interface{}{}, values[0:frmt.operandCount]...)
|
||||
values_f := values[0:frmt.operandCount]
|
||||
values_dbg := values[frmt.operandCount:]
|
||||
if len(values_dbg) > 0 {
|
||||
//valuesF := append([]interface{}{}, values[0:frmt.operandCount]...)
|
||||
valuesF := values[0:frmt.operandCount]
|
||||
valuesDbg := values[frmt.operandCount:]
|
||||
if len(valuesDbg) > 0 {
|
||||
// Adjust frmt.format:
|
||||
// (%v instead of %s because: frmt.check)
|
||||
{
|
||||
tmp := format
|
||||
if len(tmp) > 0 {
|
||||
if unicode.IsSpace(rune(tmp[len(tmp)-1])) {
|
||||
buffer_f.WriteString("%v")
|
||||
buf.WriteString("%v")
|
||||
} else {
|
||||
buffer_f.WriteString(" %v")
|
||||
buf.WriteString(" %v")
|
||||
}
|
||||
} else if frmt.check {
|
||||
// Performing a check, so no output
|
||||
} else {
|
||||
buffer_f.WriteString("%v")
|
||||
}
|
||||
buf.WriteString("%v")
|
||||
}
|
||||
|
||||
// Adjust values_f:
|
||||
// Adjust valuesF:
|
||||
if !frmt.check {
|
||||
tmp := []string{}
|
||||
for _, value := range values_dbg {
|
||||
for _, value := range valuesDbg {
|
||||
tmp = append(tmp, fmt.Sprintf("%v", value))
|
||||
}
|
||||
// First, make a copy of values_f, so we avoid overwriting values_dbg when appending
|
||||
values_f = append([]interface{}{}, values_f...)
|
||||
values_f = append(values_f, strings.Join(tmp, " "))
|
||||
// First, make a copy of valuesF, so we avoid overwriting valuesDbg when appending
|
||||
valuesF = append([]interface{}{}, valuesF...)
|
||||
valuesF = append(valuesF, strings.Join(tmp, " "))
|
||||
}
|
||||
}
|
||||
|
||||
format = buffer_f.String()
|
||||
format = buf.String()
|
||||
if frmt.check {
|
||||
// We do not actually emit to the log, but panic if
|
||||
// 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 format == "" {
|
||||
panic(value)
|
||||
} else {
|
||||
panic(fmt.Sprintf(format, append(values_f, value)...))
|
||||
panic(fmt.Sprintf(format, append(valuesF, value)...))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.getEmit().emit(frmt, format, values_f...)
|
||||
d.getEmit().emit(frmt, format, valuesF...)
|
||||
}
|
||||
}
|
||||
|
||||
// Idiot-proof &Dbgr{}, etc.
|
||||
func (self *Dbgr) getEmit() _emit {
|
||||
if self.emit == nil {
|
||||
self.emit = standardEmit()
|
||||
func (d *Dbgr) getEmit() emit {
|
||||
if d.emit == nil {
|
||||
d.emit = standardEmit()
|
||||
}
|
||||
return self.emit
|
||||
return d.emit
|
||||
}
|
||||
|
||||
// SetOutput will accept the following as a destination for output:
|
||||
|
@ -285,26 +279,25 @@ func (self *Dbgr) getEmit() _emit {
|
|||
// io.Writer -
|
||||
// nil Reset to the default output (os.Stderr)
|
||||
// "log" Print*/Panic*/Fatal* via the "log" package
|
||||
//
|
||||
func (self *Dbgr) SetOutput(output interface{}) {
|
||||
func (d *Dbgr) SetOutput(output interface{}) {
|
||||
if output == nil {
|
||||
self.emit = standardEmit()
|
||||
d.emit = standardEmit()
|
||||
return
|
||||
}
|
||||
switch output := output.(type) {
|
||||
case *log.Logger:
|
||||
self.emit = _emitLogger{
|
||||
d.emit = emitLogger{
|
||||
logger: output,
|
||||
}
|
||||
return
|
||||
case io.Writer:
|
||||
self.emit = _emitWriter{
|
||||
d.emit = emitWriter{
|
||||
writer: output,
|
||||
}
|
||||
return
|
||||
case string:
|
||||
if output == "log" {
|
||||
self.emit = _emitLog{}
|
||||
d.emit = emitLog{}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -315,8 +308,8 @@ func (self *Dbgr) SetOutput(output interface{}) {
|
|||
// = emit = //
|
||||
// ======== //
|
||||
|
||||
func standardEmit() _emit {
|
||||
return _emitWriter{
|
||||
func standardEmit() emit {
|
||||
return emitWriter{
|
||||
writer: os.Stderr,
|
||||
}
|
||||
}
|
||||
|
@ -329,50 +322,50 @@ func ln(tmp string) string {
|
|||
return tmp
|
||||
}
|
||||
|
||||
type _emit interface {
|
||||
type emit interface {
|
||||
emit(_frmt, string, ...interface{})
|
||||
}
|
||||
|
||||
type _emitWriter struct {
|
||||
type emitWriter struct {
|
||||
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 == "" {
|
||||
fmt.Fprintln(self.writer, values...)
|
||||
fmt.Fprintln(ew.writer, values...)
|
||||
} else {
|
||||
if frmt.panic {
|
||||
panic(fmt.Sprintf(format, values...))
|
||||
}
|
||||
fmt.Fprintf(self.writer, ln(format), values...)
|
||||
fmt.Fprintf(ew.writer, ln(format), values...)
|
||||
if frmt.fatal {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type _emitLogger struct {
|
||||
type emitLogger struct {
|
||||
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 == "" {
|
||||
self.logger.Println(values...)
|
||||
el.logger.Println(values...)
|
||||
} else {
|
||||
if frmt.panic {
|
||||
self.logger.Panicf(format, values...)
|
||||
el.logger.Panicf(format, values...)
|
||||
} else if frmt.fatal {
|
||||
self.logger.Fatalf(format, values...)
|
||||
el.logger.Fatalf(format, values...)
|
||||
} 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 == "" {
|
||||
log.Println(values...)
|
||||
} else {
|
||||
|
|
133
v1/vendor/github.com/robertkrimen/otto/error.go
generated
vendored
|
@ -7,49 +7,49 @@ import (
|
|||
"github.com/robertkrimen/otto/file"
|
||||
)
|
||||
|
||||
type _exception struct {
|
||||
type exception struct {
|
||||
value interface{}
|
||||
}
|
||||
|
||||
func newException(value interface{}) *_exception {
|
||||
return &_exception{
|
||||
func newException(value interface{}) *exception {
|
||||
return &exception{
|
||||
value: value,
|
||||
}
|
||||
}
|
||||
|
||||
func (self *_exception) eject() interface{} {
|
||||
value := self.value
|
||||
self.value = nil // Prevent Go from holding on to the value, whatever it is
|
||||
func (e *exception) eject() interface{} {
|
||||
value := e.value
|
||||
e.value = nil // Prevent Go from holding on to the value, whatever it is
|
||||
return value
|
||||
}
|
||||
|
||||
type _error struct {
|
||||
type ottoError struct {
|
||||
name string
|
||||
message string
|
||||
trace []_frame
|
||||
trace []frame
|
||||
|
||||
offset int
|
||||
}
|
||||
|
||||
func (err _error) format() string {
|
||||
if len(err.name) == 0 {
|
||||
return err.message
|
||||
func (e ottoError) format() string {
|
||||
if len(e.name) == 0 {
|
||||
return e.message
|
||||
}
|
||||
if len(err.message) == 0 {
|
||||
return err.name
|
||||
if len(e.message) == 0 {
|
||||
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 {
|
||||
str := err.format() + "\n"
|
||||
for _, frame := range err.trace {
|
||||
str += " at " + frame.location() + "\n"
|
||||
func (e ottoError) formatWithStack() string {
|
||||
str := e.format() + "\n"
|
||||
for _, frm := range e.trace {
|
||||
str += " at " + frm.location() + "\n"
|
||||
}
|
||||
return str
|
||||
}
|
||||
|
||||
type _frame struct {
|
||||
type frame struct {
|
||||
native bool
|
||||
nativeFile string
|
||||
nativeLine int
|
||||
|
@ -59,13 +59,11 @@ type _frame struct {
|
|||
fn interface{}
|
||||
}
|
||||
|
||||
var (
|
||||
nativeFrame = _frame{}
|
||||
)
|
||||
var nativeFrame = frame{}
|
||||
|
||||
type _at int
|
||||
type at int
|
||||
|
||||
func (fr _frame) location() string {
|
||||
func (fr frame) location() string {
|
||||
str := "<unknown>"
|
||||
|
||||
switch {
|
||||
|
@ -95,14 +93,14 @@ func (fr _frame) location() string {
|
|||
|
||||
// An Error represents a runtime error, e.g. a TypeError, a ReferenceError, etc.
|
||||
type Error struct {
|
||||
_error
|
||||
ottoError
|
||||
}
|
||||
|
||||
// Error returns a description of the error
|
||||
//
|
||||
// TypeError: 'def' is not a function
|
||||
func (err Error) Error() string {
|
||||
return err.format()
|
||||
func (e Error) Error() string {
|
||||
return e.format()
|
||||
}
|
||||
|
||||
// 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
|
||||
// at xyz (<anonymous>:3:9)
|
||||
// at <anonymous>:7:1/
|
||||
func (err Error) String() string {
|
||||
return err.formatWithStack()
|
||||
func (e Error) String() string {
|
||||
return e.formatWithStack()
|
||||
}
|
||||
|
||||
// GoString returns a description of the error and a trace of where the
|
||||
// error occurred. Printing with %#v will trigger this behaviour.
|
||||
func (err Error) GoString() string {
|
||||
return err.formatWithStack()
|
||||
func (e Error) GoString() string {
|
||||
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...)
|
||||
}
|
||||
|
||||
func (self _error) messageValue() Value {
|
||||
if self.message == "" {
|
||||
func (e ottoError) messageValue() Value {
|
||||
if e.message == "" {
|
||||
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 {
|
||||
panic(rt.panicTypeError())
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func newError(rt *_runtime, name string, stackFramesToPop int, in ...interface{}) _error {
|
||||
err := _error{
|
||||
func newError(rt *runtime, name string, stackFramesToPop int, in ...interface{}) ottoError {
|
||||
err := ottoError{
|
||||
name: name,
|
||||
offset: -1,
|
||||
}
|
||||
|
@ -148,21 +146,21 @@ func newError(rt *_runtime, name string, stackFramesToPop int, in ...interface{}
|
|||
length := len(in)
|
||||
|
||||
if rt != nil && rt.scope != nil {
|
||||
scope := rt.scope
|
||||
curScope := rt.scope
|
||||
|
||||
for i := 0; i < stackFramesToPop; i++ {
|
||||
if scope.outer != nil {
|
||||
scope = scope.outer
|
||||
if curScope.outer != nil {
|
||||
curScope = curScope.outer
|
||||
}
|
||||
}
|
||||
|
||||
frame := scope.frame
|
||||
frm := curScope.frame
|
||||
|
||||
if length > 0 {
|
||||
if at, ok := in[length-1].(_at); ok {
|
||||
if atv, ok := in[length-1].(at); ok {
|
||||
in = in[0 : length-1]
|
||||
if scope != nil {
|
||||
frame.offset = int(at)
|
||||
if curScope != nil {
|
||||
frm.offset = int(atv)
|
||||
}
|
||||
length--
|
||||
}
|
||||
|
@ -173,54 +171,52 @@ func newError(rt *_runtime, name string, stackFramesToPop int, in ...interface{}
|
|||
|
||||
limit := rt.traceLimit
|
||||
|
||||
err.trace = append(err.trace, frame)
|
||||
if scope != nil {
|
||||
for scope = scope.outer; scope != nil; scope = scope.outer {
|
||||
err.trace = append(err.trace, frm)
|
||||
if curScope != nil {
|
||||
for curScope = curScope.outer; curScope != nil; curScope = curScope.outer {
|
||||
if limit--; limit == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
if scope.frame.offset >= 0 {
|
||||
err.trace = append(err.trace, scope.frame)
|
||||
if curScope.frame.offset >= 0 {
|
||||
err.trace = append(err.trace, curScope.frame)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if length > 0 {
|
||||
} else if length > 0 {
|
||||
description, in = in[0].(string), in[1:]
|
||||
}
|
||||
}
|
||||
err.message = err.describe(description, in...)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (rt *_runtime) panicTypeError(argumentList ...interface{}) *_exception {
|
||||
return &_exception{
|
||||
func (rt *runtime) panicTypeError(argumentList ...interface{}) *exception {
|
||||
return &exception{
|
||||
value: newError(rt, "TypeError", 0, argumentList...),
|
||||
}
|
||||
}
|
||||
|
||||
func (rt *_runtime) panicReferenceError(argumentList ...interface{}) *_exception {
|
||||
return &_exception{
|
||||
func (rt *runtime) panicReferenceError(argumentList ...interface{}) *exception {
|
||||
return &exception{
|
||||
value: newError(rt, "ReferenceError", 0, argumentList...),
|
||||
}
|
||||
}
|
||||
|
||||
func (rt *_runtime) panicURIError(argumentList ...interface{}) *_exception {
|
||||
return &_exception{
|
||||
func (rt *runtime) panicURIError(argumentList ...interface{}) *exception {
|
||||
return &exception{
|
||||
value: newError(rt, "URIError", 0, argumentList...),
|
||||
}
|
||||
}
|
||||
|
||||
func (rt *_runtime) panicSyntaxError(argumentList ...interface{}) *_exception {
|
||||
return &_exception{
|
||||
func (rt *runtime) panicSyntaxError(argumentList ...interface{}) *exception {
|
||||
return &exception{
|
||||
value: newError(rt, "SyntaxError", 0, argumentList...),
|
||||
}
|
||||
}
|
||||
|
||||
func (rt *_runtime) panicRangeError(argumentList ...interface{}) *_exception {
|
||||
return &_exception{
|
||||
func (rt *runtime) panicRangeError(argumentList ...interface{}) *exception {
|
||||
return &exception{
|
||||
value: newError(rt, "RangeError", 0, argumentList...),
|
||||
}
|
||||
}
|
||||
|
@ -228,20 +224,19 @@ func (rt *_runtime) panicRangeError(argumentList ...interface{}) *_exception {
|
|||
func catchPanic(function func()) (err error) {
|
||||
defer func() {
|
||||
if caught := recover(); caught != nil {
|
||||
if exception, ok := caught.(*_exception); ok {
|
||||
caught = exception.eject()
|
||||
if excep, ok := caught.(*exception); ok {
|
||||
caught = excep.eject()
|
||||
}
|
||||
switch caught := caught.(type) {
|
||||
case *Error:
|
||||
err = caught
|
||||
return
|
||||
case _error:
|
||||
case ottoError:
|
||||
err = &Error{caught}
|
||||
return
|
||||
case Value:
|
||||
if vl := caught._object(); vl != nil {
|
||||
switch vl := vl.value.(type) {
|
||||
case _error:
|
||||
if vl := caught.object(); vl != nil {
|
||||
if vl, ok := vl.value.(ottoError); ok {
|
||||
err = &Error{vl}
|
||||
return
|
||||
}
|
||||
|
|
117
v1/vendor/github.com/robertkrimen/otto/evaluate.go
generated
vendored
|
@ -8,12 +8,12 @@ import (
|
|||
"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
|
||||
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) {
|
||||
return NaNValue()
|
||||
}
|
||||
|
@ -26,61 +26,57 @@ func (self *_runtime) evaluateDivide(left float64, right float64) Value {
|
|||
if math.IsInf(left, 0) {
|
||||
if math.Signbit(left) == math.Signbit(right) {
|
||||
return positiveInfinityValue()
|
||||
} else {
|
||||
return negativeInfinityValue()
|
||||
}
|
||||
return negativeInfinityValue()
|
||||
}
|
||||
if math.IsInf(right, 0) {
|
||||
if math.Signbit(left) == math.Signbit(right) {
|
||||
return positiveZeroValue()
|
||||
} else {
|
||||
return negativeZeroValue()
|
||||
}
|
||||
return negativeZeroValue()
|
||||
}
|
||||
if right == 0 {
|
||||
if math.Signbit(left) == math.Signbit(right) {
|
||||
return positiveInfinityValue()
|
||||
} else {
|
||||
}
|
||||
return negativeInfinityValue()
|
||||
}
|
||||
}
|
||||
return toValue_float64(left / right)
|
||||
return float64Value(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
|
||||
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()
|
||||
|
||||
switch operator {
|
||||
// Additive
|
||||
case token.PLUS:
|
||||
leftValue = toPrimitive(leftValue)
|
||||
leftValue = toPrimitiveValue(leftValue)
|
||||
rightValue := right.resolve()
|
||||
rightValue = toPrimitive(rightValue)
|
||||
rightValue = toPrimitiveValue(rightValue)
|
||||
|
||||
if leftValue.IsString() || rightValue.IsString() {
|
||||
return toValue_string(strings.Join([]string{leftValue.string(), rightValue.string()}, ""))
|
||||
} else {
|
||||
return toValue_float64(leftValue.float64() + rightValue.float64())
|
||||
return stringValue(strings.Join([]string{leftValue.string(), rightValue.string()}, ""))
|
||||
}
|
||||
return float64Value(leftValue.float64() + rightValue.float64())
|
||||
case token.MINUS:
|
||||
rightValue := right.resolve()
|
||||
return toValue_float64(leftValue.float64() - rightValue.float64())
|
||||
return float64Value(leftValue.float64() - rightValue.float64())
|
||||
|
||||
// Multiplicative
|
||||
case token.MULTIPLY:
|
||||
rightValue := right.resolve()
|
||||
return toValue_float64(leftValue.float64() * rightValue.float64())
|
||||
return float64Value(leftValue.float64() * rightValue.float64())
|
||||
case token.SLASH:
|
||||
rightValue := right.resolve()
|
||||
return self.evaluateDivide(leftValue.float64(), rightValue.float64())
|
||||
return rt.evaluateDivide(leftValue.float64(), rightValue.float64())
|
||||
case token.REMAINDER:
|
||||
rightValue := right.resolve()
|
||||
return toValue_float64(math.Mod(leftValue.float64(), rightValue.float64()))
|
||||
return float64Value(math.Mod(leftValue.float64(), rightValue.float64()))
|
||||
|
||||
// Logical
|
||||
case token.LOGICAL_AND:
|
||||
|
@ -88,65 +84,65 @@ func (self *_runtime) calculateBinaryExpression(operator token.Token, left Value
|
|||
if !left {
|
||||
return falseValue
|
||||
}
|
||||
return toValue_bool(right.resolve().bool())
|
||||
return boolValue(right.resolve().bool())
|
||||
case token.LOGICAL_OR:
|
||||
left := leftValue.bool()
|
||||
if left {
|
||||
return trueValue
|
||||
}
|
||||
return toValue_bool(right.resolve().bool())
|
||||
return boolValue(right.resolve().bool())
|
||||
|
||||
// Bitwise
|
||||
case token.AND:
|
||||
rightValue := right.resolve()
|
||||
return toValue_int32(toInt32(leftValue) & toInt32(rightValue))
|
||||
return int32Value(toInt32(leftValue) & toInt32(rightValue))
|
||||
case token.OR:
|
||||
rightValue := right.resolve()
|
||||
return toValue_int32(toInt32(leftValue) | toInt32(rightValue))
|
||||
return int32Value(toInt32(leftValue) | toInt32(rightValue))
|
||||
case token.EXCLUSIVE_OR:
|
||||
rightValue := right.resolve()
|
||||
return toValue_int32(toInt32(leftValue) ^ toInt32(rightValue))
|
||||
return int32Value(toInt32(leftValue) ^ toInt32(rightValue))
|
||||
|
||||
// Shift
|
||||
// (Masking of 0x1f is to restrict the shift to a maximum of 31 places)
|
||||
case token.SHIFT_LEFT:
|
||||
rightValue := right.resolve()
|
||||
return toValue_int32(toInt32(leftValue) << (toUint32(rightValue) & 0x1f))
|
||||
return int32Value(toInt32(leftValue) << (toUint32(rightValue) & 0x1f))
|
||||
case token.SHIFT_RIGHT:
|
||||
rightValue := right.resolve()
|
||||
return toValue_int32(toInt32(leftValue) >> (toUint32(rightValue) & 0x1f))
|
||||
return int32Value(toInt32(leftValue) >> (toUint32(rightValue) & 0x1f))
|
||||
case token.UNSIGNED_SHIFT_RIGHT:
|
||||
rightValue := right.resolve()
|
||||
// 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:
|
||||
rightValue := right.resolve()
|
||||
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:
|
||||
rightValue := right.resolve()
|
||||
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))
|
||||
}
|
||||
|
||||
type _lessThanResult int
|
||||
type lessThanResult int
|
||||
|
||||
const (
|
||||
lessThanFalse _lessThanResult = iota
|
||||
lessThanFalse lessThanResult = iota
|
||||
lessThanTrue
|
||||
lessThanUndefined
|
||||
)
|
||||
|
||||
func calculateLessThan(left Value, right Value, leftFirst bool) _lessThanResult {
|
||||
func calculateLessThan(left Value, right Value, leftFirst bool) lessThanResult {
|
||||
var x, y Value
|
||||
if leftFirst {
|
||||
x = toNumberPrimitive(left)
|
||||
|
@ -175,46 +171,46 @@ func calculateLessThan(left Value, right Value, leftFirst bool) _lessThanResult
|
|||
return lessThanFalse
|
||||
}
|
||||
|
||||
// FIXME Probably a map is not the most efficient way to do this
|
||||
var lessThanTable [4](map[_lessThanResult]bool) = [4](map[_lessThanResult]bool){
|
||||
// FIXME Probably a map is not the most efficient way to do this.
|
||||
var lessThanTable [4](map[lessThanResult]bool) = [4](map[lessThanResult]bool){
|
||||
// <
|
||||
map[_lessThanResult]bool{
|
||||
map[lessThanResult]bool{
|
||||
lessThanFalse: false,
|
||||
lessThanTrue: true,
|
||||
lessThanUndefined: false,
|
||||
},
|
||||
|
||||
// >
|
||||
map[_lessThanResult]bool{
|
||||
map[lessThanResult]bool{
|
||||
lessThanFalse: false,
|
||||
lessThanTrue: true,
|
||||
lessThanUndefined: false,
|
||||
},
|
||||
|
||||
// <=
|
||||
map[_lessThanResult]bool{
|
||||
map[lessThanResult]bool{
|
||||
lessThanFalse: true,
|
||||
lessThanTrue: false,
|
||||
lessThanUndefined: false,
|
||||
},
|
||||
|
||||
// >=
|
||||
map[_lessThanResult]bool{
|
||||
map[lessThanResult]bool{
|
||||
lessThanFalse: true,
|
||||
lessThanTrue: 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?
|
||||
// TODO This might be redundant now (with regards to evaluateComparison)
|
||||
x := left.resolve()
|
||||
y := right.resolve()
|
||||
|
||||
kindEqualKind := false
|
||||
var kindEqualKind bool
|
||||
var negate bool
|
||||
result := true
|
||||
negate := false
|
||||
|
||||
switch comparator {
|
||||
case token.LESS:
|
||||
|
@ -238,27 +234,28 @@ func (self *_runtime) calculateComparison(comparator token.Token, left Value, ri
|
|||
negate = true
|
||||
fallthrough
|
||||
case token.EQUAL:
|
||||
if x.kind == y.kind {
|
||||
switch {
|
||||
case x.kind == y.kind:
|
||||
kindEqualKind = true
|
||||
} else if x.kind <= valueNull && y.kind <= valueNull {
|
||||
case x.kind <= valueNull && y.kind <= valueNull:
|
||||
result = true
|
||||
} else if x.kind <= valueNull || y.kind <= valueNull {
|
||||
case x.kind <= valueNull || y.kind <= valueNull:
|
||||
result = false
|
||||
} else if x.kind <= valueString && y.kind <= valueString {
|
||||
case x.kind <= valueString && y.kind <= valueString:
|
||||
result = x.float64() == y.float64()
|
||||
} else if x.kind == valueBoolean {
|
||||
result = self.calculateComparison(token.EQUAL, toValue_float64(x.float64()), y)
|
||||
} else if y.kind == valueBoolean {
|
||||
result = self.calculateComparison(token.EQUAL, x, toValue_float64(y.float64()))
|
||||
} else if x.kind == valueObject {
|
||||
result = self.calculateComparison(token.EQUAL, toPrimitive(x), y)
|
||||
} else if y.kind == valueObject {
|
||||
result = self.calculateComparison(token.EQUAL, x, toPrimitive(y))
|
||||
} else {
|
||||
panic(hereBeDragons("Unable to test for equality: %v ==? %v", x, y))
|
||||
case x.kind == valueBoolean:
|
||||
result = rt.calculateComparison(token.EQUAL, float64Value(x.float64()), y)
|
||||
case y.kind == valueBoolean:
|
||||
result = rt.calculateComparison(token.EQUAL, x, float64Value(y.float64()))
|
||||
case x.kind == valueObject:
|
||||
result = rt.calculateComparison(token.EQUAL, toPrimitiveValue(x), y)
|
||||
case y.kind == valueObject:
|
||||
result = rt.calculateComparison(token.EQUAL, x, toPrimitiveValue(y))
|
||||
default:
|
||||
panic(fmt.Sprintf("unknown types for equal: %v ==? %v", x, y))
|
||||
}
|
||||
default:
|
||||
panic(fmt.Errorf("Unknown comparator %s", comparator.String()))
|
||||
panic(fmt.Sprintf("unknown comparator %s", comparator.String()))
|
||||
}
|
||||
|
||||
if kindEqualKind {
|
||||
|
@ -278,7 +275,7 @@ func (self *_runtime) calculateComparison(comparator token.Token, left Value, ri
|
|||
case valueBoolean:
|
||||
result = x.bool() == y.bool()
|
||||
case valueObject:
|
||||
result = x._object() == y._object()
|
||||
result = x.object() == y.object()
|
||||
default:
|
||||
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
|
||||
Line int // The line number, starting at 1
|
||||
Column int // The column number, starting at 1 (The character count)
|
||||
|
||||
}
|
||||
|
||||
// A Position is valid if the line number is > 0.
|
||||
|
||||
func (self *Position) isValid() bool {
|
||||
return self.Line > 0
|
||||
func (p *Position) isValid() bool {
|
||||
return p.Line > 0
|
||||
}
|
||||
|
||||
// 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
|
||||
// file An invalid position with filename
|
||||
// - An invalid position without filename
|
||||
func (self *Position) String() string {
|
||||
str := self.Filename
|
||||
if self.isValid() {
|
||||
func (p *Position) String() string {
|
||||
str := p.Filename
|
||||
if p.isValid() {
|
||||
if str != "" {
|
||||
str += ":"
|
||||
}
|
||||
str += fmt.Sprintf("%d:%d", self.Line, self.Column)
|
||||
str += fmt.Sprintf("%d:%d", p.Line, p.Column)
|
||||
}
|
||||
if str == "" {
|
||||
str = "-"
|
||||
|
@ -49,10 +48,8 @@ func (self *Position) String() string {
|
|||
return str
|
||||
}
|
||||
|
||||
// FileSet
|
||||
|
||||
// A FileSet represents a set of source files.
|
||||
type FileSet struct {
|
||||
type FileSet struct { //nolint: golint
|
||||
files []*File
|
||||
last *File
|
||||
}
|
||||
|
@ -60,27 +57,28 @@ type FileSet struct {
|
|||
// AddFile adds a new file with the given filename and src.
|
||||
//
|
||||
// This an internal method, but exported for cross-package use.
|
||||
func (self *FileSet) AddFile(filename, src string) int {
|
||||
base := self.nextBase()
|
||||
func (fs *FileSet) AddFile(filename, src string) int {
|
||||
base := fs.nextBase()
|
||||
file := &File{
|
||||
name: filename,
|
||||
src: src,
|
||||
base: base,
|
||||
}
|
||||
self.files = append(self.files, file)
|
||||
self.last = file
|
||||
fs.files = append(fs.files, file)
|
||||
fs.last = file
|
||||
return base
|
||||
}
|
||||
|
||||
func (self *FileSet) nextBase() int {
|
||||
if self.last == nil {
|
||||
func (fs *FileSet) nextBase() int {
|
||||
if fs.last == nil {
|
||||
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 {
|
||||
for _, file := range self.files {
|
||||
// File returns the File at idx or nil if not found.
|
||||
func (fs *FileSet) File(idx Idx) *File {
|
||||
for _, file := range fs.files {
|
||||
if idx <= Idx(file.base+len(file.src)) {
|
||||
return file
|
||||
}
|
||||
|
@ -89,8 +87,8 @@ func (self *FileSet) File(idx Idx) *File {
|
|||
}
|
||||
|
||||
// Position converts an Idx in the FileSet into a Position.
|
||||
func (self *FileSet) Position(idx Idx) *Position {
|
||||
for _, file := range self.files {
|
||||
func (fs *FileSet) Position(idx Idx) *Position {
|
||||
for _, file := range fs.files {
|
||||
if idx <= Idx(file.base+len(file.src)) {
|
||||
return file.Position(idx - Idx(file.base))
|
||||
}
|
||||
|
@ -99,6 +97,7 @@ func (self *FileSet) Position(idx Idx) *Position {
|
|||
return nil
|
||||
}
|
||||
|
||||
// File represents a file to parse.
|
||||
type File struct {
|
||||
name string
|
||||
src string
|
||||
|
@ -106,6 +105,7 @@ type File struct {
|
|||
sm *sourcemap.Consumer
|
||||
}
|
||||
|
||||
// NewFile returns a new file with the given filename, src and base.
|
||||
func NewFile(filename, src string, base int) *File {
|
||||
return &File{
|
||||
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 {
|
||||
fl.sm = sm
|
||||
return fl
|
||||
}
|
||||
|
||||
// Name returns the name of fl.
|
||||
func (fl *File) Name() string {
|
||||
return fl.name
|
||||
}
|
||||
|
||||
// Source returns the source of fl.
|
||||
func (fl *File) Source() string {
|
||||
return fl.src
|
||||
}
|
||||
|
||||
// Base returns the base of fl.
|
||||
func (fl *File) Base() int {
|
||||
return fl.base
|
||||
}
|
||||
|
||||
// Position returns the position at idx or nil if not valid.
|
||||
func (fl *File) Position(idx Idx) *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 (
|
||||
prototypeValueObject = interface{}(nil)
|
||||
prototypeValueFunction = _nativeFunctionObject{
|
||||
prototypeValueFunction = nativeFunctionObject{
|
||||
call: func(_ FunctionCall) Value {
|
||||
return Value{}
|
||||
},
|
||||
}
|
||||
prototypeValueString = _stringASCII("")
|
||||
prototypeValueString = stringASCII("")
|
||||
// TODO Make this just false?
|
||||
prototypeValueBoolean = Value{
|
||||
kind: valueBoolean,
|
||||
|
@ -22,7 +22,7 @@ var (
|
|||
kind: valueNumber,
|
||||
value: 0,
|
||||
}
|
||||
prototypeValueDate = _dateObject{
|
||||
prototypeValueDate = dateObject{
|
||||
epoch: 0,
|
||||
isNaN: false,
|
||||
time: time.Unix(0, 0).UTC(),
|
||||
|
@ -31,7 +31,7 @@ var (
|
|||
value: 0,
|
||||
},
|
||||
}
|
||||
prototypeValueRegExp = _regExpObject{
|
||||
prototypeValueRegExp = regExpObject{
|
||||
regularExpression: nil,
|
||||
global: false,
|
||||
ignoreCase: false,
|
||||
|
@ -41,102 +41,101 @@ var (
|
|||
}
|
||||
)
|
||||
|
||||
func newContext() *_runtime {
|
||||
self := &_runtime{}
|
||||
func newContext() *runtime {
|
||||
rt := &runtime{}
|
||||
|
||||
self.globalStash = self.newObjectStash(nil, nil)
|
||||
self.globalObject = self.globalStash.object
|
||||
rt.globalStash = rt.newObjectStash(nil, nil)
|
||||
rt.globalObject = rt.globalStash.object
|
||||
|
||||
_newContext(self)
|
||||
rt.newContext()
|
||||
|
||||
self.eval = self.globalObject.property["eval"].value.(Value).value.(*_object)
|
||||
self.globalObject.prototype = self.global.ObjectPrototype
|
||||
rt.eval = rt.globalObject.property["eval"].value.(Value).value.(*object)
|
||||
rt.globalObject.prototype = rt.global.ObjectPrototype
|
||||
|
||||
return self
|
||||
return rt
|
||||
}
|
||||
|
||||
func (runtime *_runtime) newBaseObject() *_object {
|
||||
self := newObject(runtime, "")
|
||||
return self
|
||||
func (rt *runtime) newBaseObject() *object {
|
||||
return newObject(rt, "")
|
||||
}
|
||||
|
||||
func (runtime *_runtime) newClassObject(class string) *_object {
|
||||
return newObject(runtime, class)
|
||||
func (rt *runtime) newClassObject(class string) *object {
|
||||
return newObject(rt, class)
|
||||
}
|
||||
|
||||
func (runtime *_runtime) newPrimitiveObject(class string, value Value) *_object {
|
||||
self := runtime.newClassObject(class)
|
||||
self.value = value
|
||||
return self
|
||||
func (rt *runtime) newPrimitiveObject(class string, value Value) *object {
|
||||
o := rt.newClassObject(class)
|
||||
o.value = value
|
||||
return o
|
||||
}
|
||||
|
||||
func (self *_object) primitiveValue() Value {
|
||||
switch value := self.value.(type) {
|
||||
func (o *object) primitiveValue() Value {
|
||||
switch value := o.value.(type) {
|
||||
case Value:
|
||||
return value
|
||||
case _stringObject:
|
||||
return toValue_string(value.String())
|
||||
case stringObjecter:
|
||||
return stringValue(value.String())
|
||||
}
|
||||
return Value{}
|
||||
}
|
||||
|
||||
func (self *_object) hasPrimitive() bool {
|
||||
switch self.value.(type) {
|
||||
case Value, _stringObject:
|
||||
func (o *object) hasPrimitive() bool { //nolint: unused
|
||||
switch o.value.(type) {
|
||||
case Value, stringObjecter:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (runtime *_runtime) newObject() *_object {
|
||||
self := runtime.newClassObject(classObject)
|
||||
self.prototype = runtime.global.ObjectPrototype
|
||||
return self
|
||||
func (rt *runtime) newObject() *object {
|
||||
o := rt.newClassObject(classObjectName)
|
||||
o.prototype = rt.global.ObjectPrototype
|
||||
return o
|
||||
}
|
||||
|
||||
func (runtime *_runtime) newArray(length uint32) *_object {
|
||||
self := runtime.newArrayObject(length)
|
||||
self.prototype = runtime.global.ArrayPrototype
|
||||
return self
|
||||
func (rt *runtime) newArray(length uint32) *object {
|
||||
o := rt.newArrayObject(length)
|
||||
o.prototype = rt.global.ArrayPrototype
|
||||
return o
|
||||
}
|
||||
|
||||
func (runtime *_runtime) newArrayOf(valueArray []Value) *_object {
|
||||
self := runtime.newArray(uint32(len(valueArray)))
|
||||
func (rt *runtime) newArrayOf(valueArray []Value) *object {
|
||||
o := rt.newArray(uint32(len(valueArray)))
|
||||
for index, value := range valueArray {
|
||||
if value.isEmpty() {
|
||||
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 {
|
||||
self := runtime.newStringObject(value)
|
||||
self.prototype = runtime.global.StringPrototype
|
||||
return self
|
||||
func (rt *runtime) newString(value Value) *object {
|
||||
o := rt.newStringObject(value)
|
||||
o.prototype = rt.global.StringPrototype
|
||||
return o
|
||||
}
|
||||
|
||||
func (runtime *_runtime) newBoolean(value Value) *_object {
|
||||
self := runtime.newBooleanObject(value)
|
||||
self.prototype = runtime.global.BooleanPrototype
|
||||
return self
|
||||
func (rt *runtime) newBoolean(value Value) *object {
|
||||
o := rt.newBooleanObject(value)
|
||||
o.prototype = rt.global.BooleanPrototype
|
||||
return o
|
||||
}
|
||||
|
||||
func (runtime *_runtime) newNumber(value Value) *_object {
|
||||
self := runtime.newNumberObject(value)
|
||||
self.prototype = runtime.global.NumberPrototype
|
||||
return self
|
||||
func (rt *runtime) newNumber(value Value) *object {
|
||||
o := rt.newNumberObject(value)
|
||||
o.prototype = rt.global.NumberPrototype
|
||||
return o
|
||||
}
|
||||
|
||||
func (runtime *_runtime) newRegExp(patternValue Value, flagsValue Value) *_object {
|
||||
func (rt *runtime) newRegExp(patternValue Value, flagsValue Value) *object {
|
||||
pattern := ""
|
||||
flags := ""
|
||||
if object := patternValue._object(); object != nil && object.class == classRegExp {
|
||||
if obj := patternValue.object(); obj != nil && obj.class == classRegExpName {
|
||||
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
|
||||
flags = regExp.flags
|
||||
} 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 {
|
||||
self := runtime.newRegExpObject(pattern, flags)
|
||||
self.prototype = runtime.global.RegExpPrototype
|
||||
return self
|
||||
func (rt *runtime) newRegExpDirect(pattern string, flags string) *object {
|
||||
o := rt.newRegExpObject(pattern, flags)
|
||||
o.prototype = rt.global.RegExpPrototype
|
||||
return o
|
||||
}
|
||||
|
||||
// TODO Should (probably) be one argument, right? This is redundant
|
||||
func (runtime *_runtime) newDate(epoch float64) *_object {
|
||||
self := runtime.newDateObject(epoch)
|
||||
self.prototype = runtime.global.DatePrototype
|
||||
return self
|
||||
// TODO Should (probably) be one argument, right? This is redundant.
|
||||
func (rt *runtime) newDate(epoch float64) *object {
|
||||
o := rt.newDateObject(epoch)
|
||||
o.prototype = rt.global.DatePrototype
|
||||
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 {
|
||||
case "EvalError":
|
||||
return runtime.newEvalError(message)
|
||||
return rt.newEvalError(message)
|
||||
case "TypeError":
|
||||
return runtime.newTypeError(message)
|
||||
return rt.newTypeError(message)
|
||||
case "RangeError":
|
||||
return runtime.newRangeError(message)
|
||||
return rt.newRangeError(message)
|
||||
case "ReferenceError":
|
||||
return runtime.newReferenceError(message)
|
||||
return rt.newReferenceError(message)
|
||||
case "SyntaxError":
|
||||
return runtime.newSyntaxError(message)
|
||||
return rt.newSyntaxError(message)
|
||||
case "URIError":
|
||||
return runtime.newURIError(message)
|
||||
return rt.newURIError(message)
|
||||
}
|
||||
|
||||
self := runtime.newErrorObject(name, message, stackFramesToPop)
|
||||
self.prototype = runtime.global.ErrorPrototype
|
||||
obj := rt.newErrorObject(name, message, stackFramesToPop)
|
||||
obj.prototype = rt.global.ErrorPrototype
|
||||
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 {
|
||||
self := runtime.newNativeFunctionObject(name, file, line, _nativeFunction, 0)
|
||||
self.prototype = runtime.global.FunctionPrototype
|
||||
prototype := runtime.newObject()
|
||||
self.defineProperty("prototype", toValue_object(prototype), 0100, false)
|
||||
prototype.defineProperty("constructor", toValue_object(self), 0100, false)
|
||||
return self
|
||||
func (rt *runtime) newNativeFunction(name, file string, line int, fn nativeFunction) *object {
|
||||
o := rt.newNativeFunctionObject(name, file, line, fn, 0)
|
||||
o.prototype = rt.global.FunctionPrototype
|
||||
prototype := rt.newObject()
|
||||
o.defineProperty("prototype", objectValue(prototype), 0o100, false)
|
||||
prototype.defineProperty("constructor", objectValue(o), 0o100, false)
|
||||
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
|
||||
self := runtime.newNodeFunctionObject(node, scopeEnvironment)
|
||||
self.prototype = runtime.global.FunctionPrototype
|
||||
prototype := runtime.newObject()
|
||||
self.defineProperty("prototype", toValue_object(prototype), 0100, false)
|
||||
prototype.defineProperty("constructor", toValue_object(self), 0101, false)
|
||||
return self
|
||||
o := rt.newNodeFunctionObject(node, scopeEnvironment)
|
||||
o.prototype = rt.global.FunctionPrototype
|
||||
prototype := rt.newObject()
|
||||
o.defineProperty("prototype", objectValue(prototype), 0o100, false)
|
||||
prototype.defineProperty("constructor", objectValue(o), 0o101, false)
|
||||
return o
|
||||
}
|
||||
|
||||
// FIXME Only in one place...
|
||||
func (runtime *_runtime) newBoundFunction(target *_object, this Value, argumentList []Value) *_object {
|
||||
self := runtime.newBoundFunctionObject(target, this, argumentList)
|
||||
self.prototype = runtime.global.FunctionPrototype
|
||||
prototype := runtime.newObject()
|
||||
self.defineProperty("prototype", toValue_object(prototype), 0100, false)
|
||||
prototype.defineProperty("constructor", toValue_object(self), 0100, false)
|
||||
return self
|
||||
func (rt *runtime) newBoundFunction(target *object, this Value, argumentList []Value) *object {
|
||||
o := rt.newBoundFunctionObject(target, this, argumentList)
|
||||
o.prototype = rt.global.FunctionPrototype
|
||||
prototype := rt.newObject()
|
||||
o.defineProperty("prototype", objectValue(prototype), 0o100, false)
|
||||
prototype.defineProperty("constructor", objectValue(o), 0o100, false)
|
||||
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"
|
||||
|
||||
var (
|
||||
defaultLanguage = language.MustParse("en-US")
|
||||
)
|
||||
var defaultLanguage = language.MustParse("en-US")
|
||||
|
|
141
v1/vendor/github.com/robertkrimen/otto/object.go
generated
vendored
|
@ -1,78 +1,78 @@
|
|||
package otto
|
||||
|
||||
type _object struct {
|
||||
runtime *_runtime
|
||||
type object struct {
|
||||
runtime *runtime
|
||||
|
||||
class string
|
||||
objectClass *_objectClass
|
||||
objectClass *objectClass
|
||||
value interface{}
|
||||
|
||||
prototype *_object
|
||||
prototype *object
|
||||
extensible bool
|
||||
|
||||
property map[string]_property
|
||||
property map[string]property
|
||||
propertyOrder []string
|
||||
}
|
||||
|
||||
func newObject(runtime *_runtime, class string) *_object {
|
||||
self := &_object{
|
||||
runtime: runtime,
|
||||
func newObject(rt *runtime, class string) *object {
|
||||
o := &object{
|
||||
runtime: rt,
|
||||
class: class,
|
||||
objectClass: _classObject,
|
||||
property: make(map[string]_property),
|
||||
objectClass: classObject,
|
||||
property: make(map[string]property),
|
||||
extensible: true,
|
||||
}
|
||||
return self
|
||||
return o
|
||||
}
|
||||
|
||||
// 8.12
|
||||
|
||||
// 8.12.1
|
||||
func (self *_object) getOwnProperty(name string) *_property {
|
||||
return self.objectClass.getOwnProperty(self, name)
|
||||
// 8.12.1.
|
||||
func (o *object) getOwnProperty(name string) *property {
|
||||
return o.objectClass.getOwnProperty(o, name)
|
||||
}
|
||||
|
||||
// 8.12.2
|
||||
func (self *_object) getProperty(name string) *_property {
|
||||
return self.objectClass.getProperty(self, name)
|
||||
// 8.12.2.
|
||||
func (o *object) getProperty(name string) *property {
|
||||
return o.objectClass.getProperty(o, name)
|
||||
}
|
||||
|
||||
// 8.12.3
|
||||
func (self *_object) get(name string) Value {
|
||||
return self.objectClass.get(self, name)
|
||||
// 8.12.3.
|
||||
func (o *object) get(name string) Value {
|
||||
return o.objectClass.get(o, name)
|
||||
}
|
||||
|
||||
// 8.12.4
|
||||
func (self *_object) canPut(name string) bool {
|
||||
return self.objectClass.canPut(self, name)
|
||||
// 8.12.4.
|
||||
func (o *object) canPut(name string) bool {
|
||||
return o.objectClass.canPut(o, name)
|
||||
}
|
||||
|
||||
// 8.12.5
|
||||
func (self *_object) put(name string, value Value, throw bool) {
|
||||
self.objectClass.put(self, name, value, throw)
|
||||
// 8.12.5.
|
||||
func (o *object) put(name string, value Value, throw bool) {
|
||||
o.objectClass.put(o, name, value, throw)
|
||||
}
|
||||
|
||||
// 8.12.6
|
||||
func (self *_object) hasProperty(name string) bool {
|
||||
return self.objectClass.hasProperty(self, name)
|
||||
// 8.12.6.
|
||||
func (o *object) hasProperty(name string) bool {
|
||||
return o.objectClass.hasProperty(o, name)
|
||||
}
|
||||
|
||||
func (self *_object) hasOwnProperty(name string) bool {
|
||||
return self.objectClass.hasOwnProperty(self, name)
|
||||
func (o *object) hasOwnProperty(name string) bool {
|
||||
return o.objectClass.hasOwnProperty(o, name)
|
||||
}
|
||||
|
||||
type _defaultValueHint int
|
||||
type defaultValueHint int
|
||||
|
||||
const (
|
||||
defaultValueNoHint _defaultValueHint = iota
|
||||
defaultValueNoHint defaultValueHint = iota
|
||||
defaultValueHintString
|
||||
defaultValueHintNumber
|
||||
)
|
||||
|
||||
// 8.12.8
|
||||
func (self *_object) DefaultValue(hint _defaultValueHint) Value {
|
||||
// 8.12.8.
|
||||
func (o *object) DefaultValue(hint defaultValueHint) Value {
|
||||
if hint == defaultValueNoHint {
|
||||
if self.class == classDate {
|
||||
if o.class == classDateName {
|
||||
// Date exception
|
||||
hint = defaultValueHintString
|
||||
} else {
|
||||
|
@ -84,72 +84,67 @@ func (self *_object) DefaultValue(hint _defaultValueHint) Value {
|
|||
methodSequence = []string{"toString", "valueOf"}
|
||||
}
|
||||
for _, methodName := range methodSequence {
|
||||
method := self.get(methodName)
|
||||
method := o.get(methodName)
|
||||
// FIXME This is redundant...
|
||||
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() {
|
||||
return result
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
panic(self.runtime.panicTypeError())
|
||||
panic(o.runtime.panicTypeError("Object.DefaultValue unknown"))
|
||||
}
|
||||
|
||||
func (self *_object) String() string {
|
||||
return self.DefaultValue(defaultValueHintString).string()
|
||||
func (o *object) String() string {
|
||||
return o.DefaultValue(defaultValueHintString).string()
|
||||
}
|
||||
|
||||
func (self *_object) defineProperty(name string, value Value, mode _propertyMode, throw bool) bool {
|
||||
return self.defineOwnProperty(name, _property{value, mode}, throw)
|
||||
func (o *object) defineProperty(name string, value Value, mode propertyMode, throw bool) bool { //nolint: unparam
|
||||
return o.defineOwnProperty(name, property{value, mode}, throw)
|
||||
}
|
||||
|
||||
// 8.12.9
|
||||
func (self *_object) defineOwnProperty(name string, descriptor _property, throw bool) bool {
|
||||
return self.objectClass.defineOwnProperty(self, name, descriptor, throw)
|
||||
// 8.12.9.
|
||||
func (o *object) defineOwnProperty(name string, descriptor property, throw bool) bool {
|
||||
return o.objectClass.defineOwnProperty(o, name, descriptor, throw)
|
||||
}
|
||||
|
||||
func (self *_object) delete(name string, throw bool) bool {
|
||||
return self.objectClass.delete(self, name, throw)
|
||||
func (o *object) delete(name string, throw bool) bool {
|
||||
return o.objectClass.delete(o, name, throw)
|
||||
}
|
||||
|
||||
func (self *_object) enumerate(all bool, each func(string) bool) {
|
||||
self.objectClass.enumerate(self, all, each)
|
||||
func (o *object) enumerate(all bool, each func(string) bool) {
|
||||
o.objectClass.enumerate(o, all, each)
|
||||
}
|
||||
|
||||
func (self *_object) _exists(name string) bool {
|
||||
_, exists := self.property[name]
|
||||
return exists
|
||||
func (o *object) readProperty(name string) (property, bool) {
|
||||
prop, exists := o.property[name]
|
||||
return prop, exists
|
||||
}
|
||||
|
||||
func (self *_object) _read(name string) (_property, bool) {
|
||||
property, exists := self.property[name]
|
||||
return property, exists
|
||||
}
|
||||
|
||||
func (self *_object) _write(name string, value interface{}, mode _propertyMode) {
|
||||
func (o *object) writeProperty(name string, value interface{}, mode propertyMode) {
|
||||
if value == nil {
|
||||
value = Value{}
|
||||
}
|
||||
_, exists := self.property[name]
|
||||
self.property[name] = _property{value, mode}
|
||||
if !exists {
|
||||
self.propertyOrder = append(self.propertyOrder, name)
|
||||
if _, exists := o.property[name]; !exists {
|
||||
o.propertyOrder = append(o.propertyOrder, name)
|
||||
}
|
||||
o.property[name] = property{value, mode}
|
||||
}
|
||||
|
||||
func (self *_object) _delete(name string) {
|
||||
_, exists := self.property[name]
|
||||
delete(self.property, name)
|
||||
if exists {
|
||||
for index, property := range self.propertyOrder {
|
||||
if name == property {
|
||||
if index == len(self.propertyOrder)-1 {
|
||||
self.propertyOrder = self.propertyOrder[:index]
|
||||
} else {
|
||||
self.propertyOrder = append(self.propertyOrder[:index], self.propertyOrder[index+1:]...)
|
||||
func (o *object) deleteProperty(name string) {
|
||||
if _, exists := o.property[name]; !exists {
|
||||
return
|
||||
}
|
||||
|
||||
delete(o.property, name)
|
||||
for index, prop := range o.propertyOrder {
|
||||
if name == prop {
|
||||
if index == len(o.propertyOrder)-1 {
|
||||
o.propertyOrder = o.propertyOrder[:index]
|
||||
} else {
|
||||
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"
|
||||
)
|
||||
|
||||
type _objectClass struct {
|
||||
getOwnProperty func(*_object, string) *_property
|
||||
getProperty func(*_object, string) *_property
|
||||
get func(*_object, string) Value
|
||||
canPut func(*_object, string) bool
|
||||
put func(*_object, string, Value, bool)
|
||||
hasProperty func(*_object, string) bool
|
||||
hasOwnProperty func(*_object, string) bool
|
||||
defineOwnProperty func(*_object, string, _property, bool) bool
|
||||
delete func(*_object, string, bool) bool
|
||||
enumerate func(*_object, bool, func(string) bool)
|
||||
clone func(*_object, *_object, *_clone) *_object
|
||||
marshalJSON func(*_object) json.Marshaler
|
||||
type objectClass struct {
|
||||
getOwnProperty func(*object, string) *property
|
||||
getProperty func(*object, string) *property
|
||||
get func(*object, string) Value
|
||||
canPut func(*object, string) bool
|
||||
put func(*object, string, Value, bool)
|
||||
hasProperty func(*object, string) bool
|
||||
hasOwnProperty func(*object, string) bool
|
||||
defineOwnProperty func(*object, string, property, bool) bool
|
||||
delete func(*object, string, bool) bool
|
||||
enumerate func(*object, bool, func(string) bool)
|
||||
clone func(*object, *object, *cloner) *object
|
||||
marshalJSON func(*object) json.Marshaler
|
||||
}
|
||||
|
||||
func objectEnumerate(self *_object, all bool, each func(string) bool) {
|
||||
for _, name := range self.propertyOrder {
|
||||
if all || self.property[name].enumerable() {
|
||||
func objectEnumerate(obj *object, all bool, each func(string) bool) {
|
||||
for _, name := range obj.propertyOrder {
|
||||
if all || obj.property[name].enumerable() {
|
||||
if !each(name) {
|
||||
return
|
||||
}
|
||||
|
@ -29,20 +29,17 @@ func objectEnumerate(self *_object, all bool, each func(string) bool) {
|
|||
}
|
||||
}
|
||||
|
||||
var (
|
||||
_classObject,
|
||||
_classArray,
|
||||
_classString,
|
||||
_classArguments,
|
||||
_classGoStruct,
|
||||
_classGoMap,
|
||||
_classGoArray,
|
||||
_classGoSlice,
|
||||
_ *_objectClass
|
||||
)
|
||||
var classObject,
|
||||
classArray,
|
||||
classString,
|
||||
classArguments,
|
||||
classGoStruct,
|
||||
classGoMap,
|
||||
classGoArray,
|
||||
classGoSlice *objectClass
|
||||
|
||||
func init() {
|
||||
_classObject = &_objectClass{
|
||||
classObject = &objectClass{
|
||||
objectGetOwnProperty,
|
||||
objectGetProperty,
|
||||
objectGet,
|
||||
|
@ -57,7 +54,7 @@ func init() {
|
|||
nil,
|
||||
}
|
||||
|
||||
_classArray = &_objectClass{
|
||||
classArray = &objectClass{
|
||||
objectGetOwnProperty,
|
||||
objectGetProperty,
|
||||
objectGet,
|
||||
|
@ -72,7 +69,7 @@ func init() {
|
|||
nil,
|
||||
}
|
||||
|
||||
_classString = &_objectClass{
|
||||
classString = &objectClass{
|
||||
stringGetOwnProperty,
|
||||
objectGetProperty,
|
||||
objectGet,
|
||||
|
@ -87,7 +84,7 @@ func init() {
|
|||
nil,
|
||||
}
|
||||
|
||||
_classArguments = &_objectClass{
|
||||
classArguments = &objectClass{
|
||||
argumentsGetOwnProperty,
|
||||
objectGetProperty,
|
||||
argumentsGet,
|
||||
|
@ -102,7 +99,7 @@ func init() {
|
|||
nil,
|
||||
}
|
||||
|
||||
_classGoStruct = &_objectClass{
|
||||
classGoStruct = &objectClass{
|
||||
goStructGetOwnProperty,
|
||||
objectGetProperty,
|
||||
objectGet,
|
||||
|
@ -117,7 +114,7 @@ func init() {
|
|||
goStructMarshalJSON,
|
||||
}
|
||||
|
||||
_classGoMap = &_objectClass{
|
||||
classGoMap = &objectClass{
|
||||
goMapGetOwnProperty,
|
||||
objectGetProperty,
|
||||
objectGet,
|
||||
|
@ -132,7 +129,7 @@ func init() {
|
|||
nil,
|
||||
}
|
||||
|
||||
_classGoArray = &_objectClass{
|
||||
classGoArray = &objectClass{
|
||||
goArrayGetOwnProperty,
|
||||
objectGetProperty,
|
||||
objectGet,
|
||||
|
@ -147,7 +144,7 @@ func init() {
|
|||
nil,
|
||||
}
|
||||
|
||||
_classGoSlice = &_objectClass{
|
||||
classGoSlice = &objectClass{
|
||||
goSliceGetOwnProperty,
|
||||
objectGetProperty,
|
||||
objectGet,
|
||||
|
@ -165,85 +162,81 @@ func init() {
|
|||
|
||||
// Allons-y
|
||||
|
||||
// 8.12.1
|
||||
func objectGetOwnProperty(self *_object, name string) *_property {
|
||||
// Return a _copy_ of the property
|
||||
property, exists := self._read(name)
|
||||
// 8.12.1.
|
||||
func objectGetOwnProperty(obj *object, name string) *property {
|
||||
// Return a _copy_ of the prop
|
||||
prop, exists := obj.readProperty(name)
|
||||
if !exists {
|
||||
return nil
|
||||
}
|
||||
return &property
|
||||
return &prop
|
||||
}
|
||||
|
||||
// 8.12.2
|
||||
func objectGetProperty(self *_object, name string) *_property {
|
||||
property := self.getOwnProperty(name)
|
||||
if property != nil {
|
||||
return property
|
||||
// 8.12.2.
|
||||
func objectGetProperty(obj *object, name string) *property {
|
||||
prop := obj.getOwnProperty(name)
|
||||
if prop != nil {
|
||||
return prop
|
||||
}
|
||||
if self.prototype != nil {
|
||||
return self.prototype.getProperty(name)
|
||||
if obj.prototype != nil {
|
||||
return obj.prototype.getProperty(name)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 8.12.3
|
||||
func objectGet(self *_object, name string) Value {
|
||||
property := self.getProperty(name)
|
||||
if property != nil {
|
||||
return property.get(self)
|
||||
// 8.12.3.
|
||||
func objectGet(obj *object, name string) Value {
|
||||
if prop := obj.getProperty(name); prop != nil {
|
||||
return prop.get(obj)
|
||||
}
|
||||
return Value{}
|
||||
}
|
||||
|
||||
// 8.12.4
|
||||
func objectCanPut(self *_object, name string) bool {
|
||||
canPut, _, _ := _objectCanPut(self, name)
|
||||
// 8.12.4.
|
||||
func objectCanPut(obj *object, name string) bool {
|
||||
canPut, _, _ := objectCanPutDetails(obj, name)
|
||||
return canPut
|
||||
}
|
||||
|
||||
func _objectCanPut(self *_object, name string) (canPut bool, property *_property, setter *_object) {
|
||||
property = self.getOwnProperty(name)
|
||||
if property != nil {
|
||||
switch propertyValue := property.value.(type) {
|
||||
func objectCanPutDetails(obj *object, name string) (canPut bool, prop *property, setter *object) { //nolint: nonamedreturns
|
||||
prop = obj.getOwnProperty(name)
|
||||
if prop != nil {
|
||||
switch propertyValue := prop.value.(type) {
|
||||
case Value:
|
||||
canPut = property.writable()
|
||||
return
|
||||
case _propertyGetSet:
|
||||
return prop.writable(), prop, nil
|
||||
case propertyGetSet:
|
||||
setter = propertyValue[1]
|
||||
canPut = setter != nil
|
||||
return
|
||||
return setter != nil, prop, setter
|
||||
default:
|
||||
panic(self.runtime.panicTypeError())
|
||||
panic(obj.runtime.panicTypeError("unexpected type %T to Object.CanPutDetails", prop.value))
|
||||
}
|
||||
}
|
||||
|
||||
if self.prototype == nil {
|
||||
return self.extensible, nil, nil
|
||||
if obj.prototype == nil {
|
||||
return obj.extensible, nil, nil
|
||||
}
|
||||
|
||||
property = self.prototype.getProperty(name)
|
||||
if property == nil {
|
||||
return self.extensible, nil, nil
|
||||
prop = obj.prototype.getProperty(name)
|
||||
if prop == nil {
|
||||
return obj.extensible, nil, nil
|
||||
}
|
||||
|
||||
switch propertyValue := property.value.(type) {
|
||||
switch propertyValue := prop.value.(type) {
|
||||
case Value:
|
||||
if !self.extensible {
|
||||
if !obj.extensible {
|
||||
return false, nil, nil
|
||||
}
|
||||
return property.writable(), nil, nil
|
||||
case _propertyGetSet:
|
||||
return prop.writable(), nil, nil
|
||||
case propertyGetSet:
|
||||
setter = propertyValue[1]
|
||||
canPut = setter != nil
|
||||
return
|
||||
return setter != nil, prop, setter
|
||||
default:
|
||||
panic(self.runtime.panicTypeError())
|
||||
panic(obj.runtime.panicTypeError("unexpected type %T to Object.CanPutDetails", prop.value))
|
||||
}
|
||||
}
|
||||
|
||||
// 8.12.5
|
||||
func objectPut(self *_object, name string, value Value, throw bool) {
|
||||
// 8.12.5.
|
||||
func objectPut(obj *object, name string, value Value, throw bool) {
|
||||
if true {
|
||||
// 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
|
||||
// something to detect that here, so that we do not use an
|
||||
// incompatible canPut routine
|
||||
canPut, property, setter := _objectCanPut(self, name)
|
||||
if !canPut {
|
||||
self.runtime.typeErrorResult(throw)
|
||||
} else if setter != nil {
|
||||
setter.call(toValue(self), []Value{value}, false, nativeFrame)
|
||||
} else if property != nil {
|
||||
property.value = value
|
||||
self.defineOwnProperty(name, *property, throw)
|
||||
} else {
|
||||
self.defineProperty(name, value, 0111, throw)
|
||||
canPut, prop, setter := objectCanPutDetails(obj, name)
|
||||
switch {
|
||||
case !canPut:
|
||||
obj.runtime.typeErrorResult(throw)
|
||||
case setter != nil:
|
||||
setter.call(toValue(obj), []Value{value}, false, nativeFrame)
|
||||
case prop != nil:
|
||||
prop.value = value
|
||||
obj.defineOwnProperty(name, *prop, throw)
|
||||
default:
|
||||
obj.defineProperty(name, value, 0o111, throw)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
@ -270,69 +264,77 @@ func objectPut(self *_object, name string, value Value, throw bool) {
|
|||
// The long way...
|
||||
//
|
||||
// Right now, code should never get here, see above
|
||||
if !self.canPut(name) {
|
||||
self.runtime.typeErrorResult(throw)
|
||||
if !obj.canPut(name) {
|
||||
obj.runtime.typeErrorResult(throw)
|
||||
return
|
||||
}
|
||||
|
||||
property := self.getOwnProperty(name)
|
||||
if property == nil {
|
||||
property = self.getProperty(name)
|
||||
if property != nil {
|
||||
if getSet, isAccessor := property.value.(_propertyGetSet); isAccessor {
|
||||
getSet[1].call(toValue(self), []Value{value}, false, nativeFrame)
|
||||
prop := obj.getOwnProperty(name)
|
||||
if prop == nil {
|
||||
prop = obj.getProperty(name)
|
||||
if prop != nil {
|
||||
if getSet, isAccessor := prop.value.(propertyGetSet); isAccessor {
|
||||
getSet[1].call(toValue(obj), []Value{value}, false, nativeFrame)
|
||||
return
|
||||
}
|
||||
}
|
||||
self.defineProperty(name, value, 0111, throw)
|
||||
} else {
|
||||
switch propertyValue := property.value.(type) {
|
||||
obj.defineProperty(name, value, 0o111, throw)
|
||||
return
|
||||
}
|
||||
|
||||
switch propertyValue := prop.value.(type) {
|
||||
case Value:
|
||||
property.value = value
|
||||
self.defineOwnProperty(name, *property, throw)
|
||||
case _propertyGetSet:
|
||||
prop.value = value
|
||||
obj.defineOwnProperty(name, *prop, throw)
|
||||
case propertyGetSet:
|
||||
if propertyValue[1] != nil {
|
||||
propertyValue[1].call(toValue(self), []Value{value}, false, nativeFrame)
|
||||
propertyValue[1].call(toValue(obj), []Value{value}, false, nativeFrame)
|
||||
return
|
||||
}
|
||||
if throw {
|
||||
panic(self.runtime.panicTypeError())
|
||||
panic(obj.runtime.panicTypeError("Object.Put nil second parameter to propertyGetSet"))
|
||||
}
|
||||
default:
|
||||
panic(self.runtime.panicTypeError())
|
||||
}
|
||||
panic(obj.runtime.panicTypeError("Object.Put unexpected type %T", prop.value))
|
||||
}
|
||||
}
|
||||
|
||||
// 8.12.6
|
||||
func objectHasProperty(self *_object, name string) bool {
|
||||
return self.getProperty(name) != nil
|
||||
// 8.12.6.
|
||||
func objectHasProperty(obj *object, name string) bool {
|
||||
return obj.getProperty(name) != nil
|
||||
}
|
||||
|
||||
func objectHasOwnProperty(self *_object, name string) bool {
|
||||
return self.getOwnProperty(name) != nil
|
||||
func objectHasOwnProperty(obj *object, name string) bool {
|
||||
return obj.getOwnProperty(name) != nil
|
||||
}
|
||||
|
||||
// 8.12.9
|
||||
func objectDefineOwnProperty(self *_object, name string, descriptor _property, throw bool) bool {
|
||||
property, exists := self._read(name)
|
||||
{
|
||||
// 8.12.9.
|
||||
func objectDefineOwnProperty(obj *object, name string, descriptor property, throw bool) bool {
|
||||
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 !self.extensible {
|
||||
goto Reject
|
||||
if !obj.extensible {
|
||||
return reject("not exists and not extensible")
|
||||
}
|
||||
if newGetSet, isAccessor := descriptor.value.(_propertyGetSet); isAccessor {
|
||||
if newGetSet[0] == &_nilGetSetObject {
|
||||
if newGetSet, isAccessor := descriptor.value.(propertyGetSet); isAccessor {
|
||||
if newGetSet[0] == &nilGetSetObject {
|
||||
newGetSet[0] = nil
|
||||
}
|
||||
if newGetSet[1] == &_nilGetSetObject {
|
||||
if newGetSet[1] == &nilGetSetObject {
|
||||
newGetSet[1] = nil
|
||||
}
|
||||
descriptor.value = newGetSet
|
||||
}
|
||||
self._write(name, descriptor.value, descriptor.mode)
|
||||
obj.writeProperty(name, descriptor.value, descriptor.mode)
|
||||
return true
|
||||
}
|
||||
|
||||
if descriptor.isEmpty() {
|
||||
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
|
||||
// the current and new (define) properties are the same
|
||||
|
||||
configurable := property.configurable()
|
||||
configurable := prop.configurable()
|
||||
if !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
|
||||
// be the same as the existing property
|
||||
if descriptor.enumerateSet() && descriptor.enumerable() != property.enumerable() {
|
||||
goto Reject
|
||||
if descriptor.enumerateSet() && descriptor.enumerable() != prop.enumerable() {
|
||||
return reject("property not configurable and enumerable miss match")
|
||||
}
|
||||
}
|
||||
value, isDataDescriptor := property.value.(Value)
|
||||
getSet, _ := property.value.(_propertyGetSet)
|
||||
if descriptor.isGenericDescriptor() {
|
||||
|
||||
value, isDataDescriptor := prop.value.(Value)
|
||||
getSet, _ := prop.value.(propertyGetSet)
|
||||
switch {
|
||||
case descriptor.isGenericDescriptor():
|
||||
// GenericDescriptor
|
||||
} else if isDataDescriptor != descriptor.isDataDescriptor() {
|
||||
case isDataDescriptor != descriptor.isDataDescriptor():
|
||||
// DataDescriptor <=> AccessorDescriptor
|
||||
if !configurable {
|
||||
goto Reject
|
||||
return reject("property descriptor not configurable")
|
||||
}
|
||||
} else if isDataDescriptor && descriptor.isDataDescriptor() {
|
||||
case isDataDescriptor && descriptor.isDataDescriptor():
|
||||
// DataDescriptor <=> DataDescriptor
|
||||
if !configurable {
|
||||
if !property.writable() && descriptor.writable() {
|
||||
goto Reject
|
||||
if !prop.writable() && descriptor.writable() {
|
||||
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)) {
|
||||
goto Reject
|
||||
return reject("property not configurable or writeable and descriptor not the same")
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
default:
|
||||
// AccessorDescriptor <=> AccessorDescriptor
|
||||
newGetSet, _ := descriptor.value.(_propertyGetSet)
|
||||
newGetSet, _ := descriptor.value.(propertyGetSet)
|
||||
presentGet, presentSet := true, true
|
||||
if newGetSet[0] == &_nilGetSetObject {
|
||||
if newGetSet[0] == &nilGetSetObject {
|
||||
// Present, but nil
|
||||
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]
|
||||
presentGet = false
|
||||
}
|
||||
if newGetSet[1] == &_nilGetSetObject {
|
||||
if newGetSet[1] == &nilGetSetObject {
|
||||
// Present, but nil
|
||||
newGetSet[1] = nil
|
||||
} else if newGetSet[1] == nil {
|
||||
|
@ -394,97 +398,91 @@ func objectDefineOwnProperty(self *_object, name string, descriptor _property, t
|
|||
}
|
||||
if !configurable {
|
||||
if (presentGet && (getSet[0] != newGetSet[0])) || (presentSet && (getSet[1] != newGetSet[1])) {
|
||||
goto Reject
|
||||
return reject("access descriptor not configurable")
|
||||
}
|
||||
}
|
||||
descriptor.value = newGetSet
|
||||
}
|
||||
{
|
||||
|
||||
// This section will preserve attributes of
|
||||
// the original property, if necessary
|
||||
value1 := descriptor.value
|
||||
if value1 == nil {
|
||||
value1 = property.value
|
||||
} else if newGetSet, isAccessor := descriptor.value.(_propertyGetSet); isAccessor {
|
||||
if newGetSet[0] == &_nilGetSetObject {
|
||||
value1 = prop.value
|
||||
} else if newGetSet, isAccessor := descriptor.value.(propertyGetSet); isAccessor {
|
||||
if newGetSet[0] == &nilGetSetObject {
|
||||
newGetSet[0] = nil
|
||||
}
|
||||
if newGetSet[1] == &_nilGetSetObject {
|
||||
if newGetSet[1] == &nilGetSetObject {
|
||||
newGetSet[1] = nil
|
||||
}
|
||||
value1 = newGetSet
|
||||
}
|
||||
mode1 := descriptor.mode
|
||||
if mode1&0222 != 0 {
|
||||
if mode1&0o222 != 0 {
|
||||
// TODO Factor this out into somewhere testable
|
||||
// (Maybe put into switch ...)
|
||||
mode0 := property.mode
|
||||
if mode1&0200 != 0 {
|
||||
mode0 := prop.mode
|
||||
if mode1&0o200 != 0 {
|
||||
if descriptor.isDataDescriptor() {
|
||||
mode1 &= ^0200 // Turn off "writable" missing
|
||||
mode1 |= (mode0 & 0100)
|
||||
mode1 &= ^0o200 // Turn off "writable" missing
|
||||
mode1 |= (mode0 & 0o100)
|
||||
}
|
||||
}
|
||||
if mode1&020 != 0 {
|
||||
mode1 |= (mode0 & 010)
|
||||
if mode1&0o20 != 0 {
|
||||
mode1 |= (mode0 & 0o10)
|
||||
}
|
||||
if mode1&02 != 0 {
|
||||
mode1 |= (mode0 & 01)
|
||||
if mode1&0o2 != 0 {
|
||||
mode1 |= (mode0 & 0o1)
|
||||
}
|
||||
mode1 &= 0311 // 0311 to preserve the non-setting on "writable"
|
||||
}
|
||||
self._write(name, value1, mode1)
|
||||
mode1 &= 0o311 // 0311 to preserve the non-setting on "writable"
|
||||
}
|
||||
obj.writeProperty(name, value1, mode1)
|
||||
|
||||
return true
|
||||
}
|
||||
Reject:
|
||||
if throw {
|
||||
panic(self.runtime.panicTypeError())
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func objectDelete(self *_object, name string, throw bool) bool {
|
||||
property_ := self.getOwnProperty(name)
|
||||
if property_ == nil {
|
||||
func objectDelete(obj *object, name string, throw bool) bool {
|
||||
prop := obj.getOwnProperty(name)
|
||||
if prop == nil {
|
||||
return true
|
||||
}
|
||||
if property_.configurable() {
|
||||
self._delete(name)
|
||||
if prop.configurable() {
|
||||
obj.deleteProperty(name)
|
||||
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.runtime = clone.runtime
|
||||
if out.prototype != nil {
|
||||
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))
|
||||
copy(out.propertyOrder, in.propertyOrder)
|
||||
for index, property := range in.property {
|
||||
out.property[index] = clone.property(property)
|
||||
for index, prop := range in.property {
|
||||
out.property[index] = clone.property(prop)
|
||||
}
|
||||
|
||||
switch value := in.value.(type) {
|
||||
case _nativeFunctionObject:
|
||||
case nativeFunctionObject:
|
||||
out.value = value
|
||||
case _bindFunctionObject:
|
||||
out.value = _bindFunctionObject{
|
||||
case bindFunctionObject:
|
||||
out.value = bindFunctionObject{
|
||||
target: clone.object(value.target),
|
||||
this: clone.value(value.this),
|
||||
argumentList: clone.valueArray(value.argumentList),
|
||||
}
|
||||
case _nodeFunctionObject:
|
||||
out.value = _nodeFunctionObject{
|
||||
case nodeFunctionObject:
|
||||
out.value = nodeFunctionObject{
|
||||
node: value.node,
|
||||
stash: clone.stash(value.stash),
|
||||
}
|
||||
case _argumentsObject:
|
||||
case argumentsObject:
|
||||
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
|
||||
|
||||
value, _ = vm.Run("xyzzy.length")
|
||||
{
|
||||
// value is an int64 with a value of 16
|
||||
value, _ := value.ToInteger()
|
||||
}
|
||||
// iv is an int64 with a value of 16
|
||||
iv, _ := value.ToInteger()
|
||||
|
||||
An error happens
|
||||
|
||||
|
@ -216,9 +214,7 @@ http://github.com/robertkrimen/natto
|
|||
Here is some more discussion of the issue:
|
||||
|
||||
* http://book.mixu.net/node/ch2.html
|
||||
|
||||
* http://en.wikipedia.org/wiki/Reentrancy_%28computing%29
|
||||
|
||||
* http://aaroncrane.co.uk/2009/02/perl_safe_signals/
|
||||
*/
|
||||
package otto
|
||||
|
@ -232,36 +228,41 @@ import (
|
|||
"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 {
|
||||
// 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.
|
||||
Interrupt chan func()
|
||||
runtime *_runtime
|
||||
runtime *runtime
|
||||
}
|
||||
|
||||
// New will allocate a new JavaScript runtime
|
||||
// New will allocate a new JavaScript runtime.
|
||||
func New() *Otto {
|
||||
self := &Otto{
|
||||
o := &Otto{
|
||||
runtime: newContext(),
|
||||
}
|
||||
self.runtime.otto = self
|
||||
self.runtime.traceLimit = 10
|
||||
self.Set("console", self.runtime.newConsole())
|
||||
o.runtime.otto = o
|
||||
o.runtime.traceLimit = 10
|
||||
if err := o.Set("console", o.runtime.newConsole()); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
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 {
|
||||
self := &Otto{
|
||||
runtime: otto.runtime.clone(),
|
||||
func (o *Otto) clone() *Otto {
|
||||
n := &Otto{
|
||||
runtime: o.runtime.clone(),
|
||||
}
|
||||
self.runtime.otto = self
|
||||
return self
|
||||
n.runtime.otto = n
|
||||
return n
|
||||
}
|
||||
|
||||
// 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 Program, but if the AST has been modified, then runtime behavior is undefined.
|
||||
func (self Otto) Run(src interface{}) (Value, error) {
|
||||
value, err := self.runtime.cmpl_run(src, nil)
|
||||
func (o Otto) Run(src interface{}) (Value, error) {
|
||||
value, err := o.runtime.cmplRun(src, nil)
|
||||
if !value.safe() {
|
||||
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
|
||||
// already defined in the current stack frame. This is most useful in, for
|
||||
// example, a debugger call.
|
||||
func (self Otto) Eval(src interface{}) (Value, error) {
|
||||
if self.runtime.scope == nil {
|
||||
self.runtime.enterGlobalScope()
|
||||
defer self.runtime.leaveScope()
|
||||
func (o Otto) Eval(src interface{}) (Value, error) {
|
||||
if o.runtime.scope == nil {
|
||||
o.runtime.enterGlobalScope()
|
||||
defer o.runtime.leaveScope()
|
||||
}
|
||||
|
||||
value, err := self.runtime.cmpl_eval(src, nil)
|
||||
value, err := o.runtime.cmplEval(src, nil)
|
||||
if !value.safe() {
|
||||
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
|
||||
// will be undefined.
|
||||
func (self Otto) Get(name string) (Value, error) {
|
||||
func (o Otto) Get(name string) (Value, error) {
|
||||
value := Value{}
|
||||
err := catchPanic(func() {
|
||||
value = self.getValue(name)
|
||||
value = o.getValue(name)
|
||||
})
|
||||
if !value.safe() {
|
||||
value = Value{}
|
||||
|
@ -330,8 +331,8 @@ func (self Otto) Get(name string) (Value, error) {
|
|||
return value, err
|
||||
}
|
||||
|
||||
func (self Otto) getValue(name string) Value {
|
||||
return self.runtime.globalStash.getBinding(name, false)
|
||||
func (o Otto) getValue(name string) Value {
|
||||
return o.runtime.globalStash.getBinding(name, false)
|
||||
}
|
||||
|
||||
// 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.
|
||||
//
|
||||
// If the top-level binding does not exist, it will be created.
|
||||
func (self Otto) Set(name string, value interface{}) error {
|
||||
{
|
||||
value, err := self.ToValue(value)
|
||||
func (o Otto) Set(name string, value interface{}) error {
|
||||
val, err := o.ToValue(value)
|
||||
if err != nil {
|
||||
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) {
|
||||
self.runtime.globalStash.setValue(name, value, false)
|
||||
func (o Otto) setValue(name string, value Value) {
|
||||
o.runtime.globalStash.setValue(name, value, false)
|
||||
}
|
||||
|
||||
func (self Otto) SetDebuggerHandler(fn func(vm *Otto)) {
|
||||
self.runtime.debugger = fn
|
||||
// SetDebuggerHandler sets the debugger handler to fn.
|
||||
func (o Otto) SetDebuggerHandler(fn func(vm *Otto)) {
|
||||
o.runtime.debugger = fn
|
||||
}
|
||||
|
||||
func (self Otto) SetRandomSource(fn func() float64) {
|
||||
self.runtime.random = fn
|
||||
// SetRandomSource sets the random source to fn.
|
||||
func (o Otto) SetRandomSource(fn func() float64) {
|
||||
o.runtime.random = fn
|
||||
}
|
||||
|
||||
// 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
|
||||
// happens outside the interpreter. So if your Go function is infinitely
|
||||
// recursive, you're still in trouble.
|
||||
func (self Otto) SetStackDepthLimit(limit int) {
|
||||
self.runtime.stackLimit = limit
|
||||
func (o Otto) SetStackDepthLimit(limit int) {
|
||||
o.runtime.stackLimit = limit
|
||||
}
|
||||
|
||||
// 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
|
||||
// is 10. This is consistent with V8 and SpiderMonkey.
|
||||
//
|
||||
// TODO: expose via `Error.stackTraceLimit`
|
||||
func (self Otto) SetStackTraceLimit(limit int) {
|
||||
self.runtime.traceLimit = limit
|
||||
// TODO: expose via `Error.stackTraceLimit`.
|
||||
func (o Otto) SetStackTraceLimit(limit int) {
|
||||
o.runtime.traceLimit = limit
|
||||
}
|
||||
|
||||
// MakeCustomError creates a new Error object with the given name and message,
|
||||
// returning it as a Value.
|
||||
func (self Otto) MakeCustomError(name, message string) Value {
|
||||
return self.runtime.toValue(self.runtime.newError(name, self.runtime.toValue(message), 0))
|
||||
func (o Otto) MakeCustomError(name, message string) Value {
|
||||
return o.runtime.toValue(o.runtime.newError(name, o.runtime.toValue(message), 0))
|
||||
}
|
||||
|
||||
// MakeRangeError creates a new RangeError object with the given message,
|
||||
// returning it as a Value.
|
||||
func (self Otto) MakeRangeError(message string) Value {
|
||||
return self.runtime.toValue(self.runtime.newRangeError(self.runtime.toValue(message)))
|
||||
func (o Otto) MakeRangeError(message string) Value {
|
||||
return o.runtime.toValue(o.runtime.newRangeError(o.runtime.toValue(message)))
|
||||
}
|
||||
|
||||
// MakeSyntaxError creates a new SyntaxError object with the given message,
|
||||
// returning it as a Value.
|
||||
func (self Otto) MakeSyntaxError(message string) Value {
|
||||
return self.runtime.toValue(self.runtime.newSyntaxError(self.runtime.toValue(message)))
|
||||
func (o Otto) MakeSyntaxError(message string) Value {
|
||||
return o.runtime.toValue(o.runtime.newSyntaxError(o.runtime.toValue(message)))
|
||||
}
|
||||
|
||||
// MakeTypeError creates a new TypeError object with the given message,
|
||||
// returning it as a Value.
|
||||
func (self Otto) MakeTypeError(message string) Value {
|
||||
return self.runtime.toValue(self.runtime.newTypeError(self.runtime.toValue(message)))
|
||||
func (o Otto) MakeTypeError(message string) Value {
|
||||
return o.runtime.toValue(o.runtime.newTypeError(o.runtime.toValue(message)))
|
||||
}
|
||||
|
||||
// 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
|
||||
// ten stack frames, and skipping any innermost native function stack frames.
|
||||
func (self Otto) Context() Context {
|
||||
return self.ContextSkip(10, true)
|
||||
func (o Otto) Context() Context {
|
||||
return o.ContextSkip(10, true)
|
||||
}
|
||||
|
||||
// ContextLimit returns the current execution context of the vm, with a
|
||||
// specific limit on the number of stack frames to traverse, skipping any
|
||||
// innermost native function stack frames.
|
||||
func (self Otto) ContextLimit(limit int) Context {
|
||||
return self.ContextSkip(limit, true)
|
||||
func (o Otto) ContextLimit(limit int) Context {
|
||||
return o.ContextSkip(limit, true)
|
||||
}
|
||||
|
||||
// ContextSkip returns the current execution context of the vm, with a
|
||||
// specific limit on the number of stack frames to traverse, optionally
|
||||
// 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
|
||||
if self.runtime.scope == nil {
|
||||
self.runtime.enterGlobalScope()
|
||||
defer self.runtime.leaveScope()
|
||||
if o.runtime.scope == nil {
|
||||
o.runtime.enterGlobalScope()
|
||||
defer o.runtime.leaveScope()
|
||||
}
|
||||
|
||||
scope := self.runtime.scope
|
||||
frame := scope.frame
|
||||
curScope := o.runtime.scope
|
||||
frm := curScope.frame
|
||||
|
||||
for skipNative && frame.native && scope.outer != nil {
|
||||
scope = scope.outer
|
||||
frame = scope.frame
|
||||
for skipNative && frm.native && curScope.outer != nil {
|
||||
curScope = curScope.outer
|
||||
frm = curScope.frame
|
||||
}
|
||||
|
||||
// Get location information
|
||||
var ctx Context
|
||||
ctx.Filename = "<unknown>"
|
||||
ctx.Callee = frame.callee
|
||||
ctx.Callee = frm.callee
|
||||
|
||||
switch {
|
||||
case frame.native:
|
||||
ctx.Filename = frame.nativeFile
|
||||
ctx.Line = frame.nativeLine
|
||||
case frm.native:
|
||||
ctx.Filename = frm.nativeFile
|
||||
ctx.Line = frm.nativeLine
|
||||
ctx.Column = 0
|
||||
case frame.file != nil:
|
||||
case frm.file != nil:
|
||||
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.Column = p.Column
|
||||
|
||||
|
@ -479,14 +481,14 @@ func (self Otto) ContextSkip(limit int, skipNative bool) (ctx Context) {
|
|||
}
|
||||
|
||||
// Get the current scope this Value
|
||||
ctx.This = toValue_object(scope.this)
|
||||
ctx.This = objectValue(curScope.this)
|
||||
|
||||
// Build stacktrace (up to 10 levels deep)
|
||||
ctx.Symbols = make(map[string]Value)
|
||||
ctx.Stacktrace = append(ctx.Stacktrace, frame.location())
|
||||
ctx.Stacktrace = append(ctx.Stacktrace, frm.location())
|
||||
for limit != 0 {
|
||||
// Get variables
|
||||
stash := scope.lexical
|
||||
stash := curScope.lexical
|
||||
for {
|
||||
for _, name := range getStashProperties(stash) {
|
||||
if _, ok := ctx.Symbols[name]; !ok {
|
||||
|
@ -499,17 +501,17 @@ func (self Otto) ContextSkip(limit int, skipNative bool) (ctx Context) {
|
|||
}
|
||||
}
|
||||
|
||||
scope = scope.outer
|
||||
if scope == nil {
|
||||
curScope = curScope.outer
|
||||
if curScope == nil {
|
||||
break
|
||||
}
|
||||
if scope.frame.offset >= 0 {
|
||||
ctx.Stacktrace = append(ctx.Stacktrace, scope.frame.location())
|
||||
if curScope.frame.offset >= 0 {
|
||||
ctx.Stacktrace = append(ctx.Stacktrace, curScope.frame.location())
|
||||
}
|
||||
limit--
|
||||
}
|
||||
|
||||
return
|
||||
return ctx
|
||||
}
|
||||
|
||||
// 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
|
||||
// // 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")
|
||||
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{}
|
||||
|
||||
construct := false
|
||||
|
@ -541,19 +543,19 @@ func (self Otto) Call(source string, this interface{}, argumentList ...interface
|
|||
}
|
||||
|
||||
// FIXME enterGlobalScope
|
||||
self.runtime.enterGlobalScope()
|
||||
o.runtime.enterGlobalScope()
|
||||
defer func() {
|
||||
self.runtime.leaveScope()
|
||||
o.runtime.leaveScope()
|
||||
}()
|
||||
|
||||
if !construct && this == nil {
|
||||
program, err := self.runtime.cmpl_parse("", source+"()", nil)
|
||||
program, err := o.runtime.cmplParse("", source+"()", nil)
|
||||
if err == nil {
|
||||
if node, ok := program.body[0].(*_nodeExpressionStatement); ok {
|
||||
if node, ok := node.expression.(*_nodeCallExpression); ok {
|
||||
if node, ok := program.body[0].(*nodeExpressionStatement); ok {
|
||||
if node, ok := node.expression.(*nodeCallExpression); ok {
|
||||
var value Value
|
||||
err := catchPanic(func() {
|
||||
value = self.runtime.cmpl_evaluate_nodeCallExpression(node, argumentList)
|
||||
value = o.runtime.cmplEvaluateNodeCallExpression(node, argumentList)
|
||||
})
|
||||
if err != nil {
|
||||
return Value{}, err
|
||||
|
@ -563,35 +565,32 @@ func (self Otto) Call(source string, this interface{}, argumentList ...interface
|
|||
}
|
||||
}
|
||||
} else {
|
||||
value, err := self.ToValue(this)
|
||||
value, err := o.ToValue(this)
|
||||
if err != nil {
|
||||
return Value{}, err
|
||||
}
|
||||
thisValue = value
|
||||
}
|
||||
|
||||
{
|
||||
this := thisValue
|
||||
|
||||
fn, err := self.Run(source)
|
||||
val := thisValue
|
||||
fn, err := o.Run(source)
|
||||
if err != nil {
|
||||
return Value{}, err
|
||||
}
|
||||
|
||||
if construct {
|
||||
result, err := fn.constructSafe(self.runtime, this, argumentList...)
|
||||
result, err := fn.constructSafe(o.runtime, val, argumentList...)
|
||||
if err != nil {
|
||||
return Value{}, err
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
result, err := fn.Call(this, argumentList...)
|
||||
result, err := fn.Call(val, argumentList...)
|
||||
if err != nil {
|
||||
return Value{}, err
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
// nil and an error is returned.
|
||||
func (self Otto) Object(source string) (*Object, error) {
|
||||
value, err := self.runtime.cmpl_run(source, nil)
|
||||
func (o Otto) Object(source string) (*Object, error) {
|
||||
value, err := o.runtime.cmplRun(source, nil)
|
||||
if err != nil {
|
||||
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.
|
||||
func (self Otto) ToValue(value interface{}) (Value, error) {
|
||||
return self.runtime.safeToValue(value)
|
||||
func (o Otto) ToValue(value interface{}) (Value, error) {
|
||||
return o.runtime.safeToValue(value)
|
||||
}
|
||||
|
||||
// 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.
|
||||
//
|
||||
// Be on the lookout for memory leaks or inadvertent sharing of resources.
|
||||
func (in *Otto) Copy() *Otto {
|
||||
func (o *Otto) Copy() *Otto {
|
||||
out := &Otto{
|
||||
runtime: in.runtime.clone(),
|
||||
runtime: o.runtime.clone(),
|
||||
}
|
||||
out.runtime.otto = out
|
||||
return out
|
||||
}
|
||||
|
||||
// Object{}
|
||||
|
||||
// Object is the representation of a JavaScript object.
|
||||
type Object struct {
|
||||
object *_object
|
||||
object *object
|
||||
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.
|
||||
//
|
||||
// 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
|
||||
// 2. The property is not actually a function
|
||||
// 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...
|
||||
// e.g., Object("JSON").Call("stringify", ...)
|
||||
|
||||
function, err := self.Get(name)
|
||||
function, err := o.Get(name)
|
||||
if err != nil {
|
||||
return Value{}, err
|
||||
}
|
||||
return function.Call(self.Value(), argumentList...)
|
||||
return function.Call(o.Value(), argumentList...)
|
||||
}
|
||||
|
||||
// Value will return self as a value.
|
||||
func (self Object) Value() Value {
|
||||
return self.value
|
||||
// Value returns the value of o.
|
||||
func (o Object) Value() Value {
|
||||
return o.value
|
||||
}
|
||||
|
||||
// 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{}
|
||||
err := catchPanic(func() {
|
||||
value = self.object.get(name)
|
||||
value = o.object.get(name)
|
||||
})
|
||||
if !value.safe() {
|
||||
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),
|
||||
// or there is an error during conversion of the given value.
|
||||
func (self Object) Set(name string, value interface{}) error {
|
||||
{
|
||||
value, err := self.object.runtime.safeToValue(value)
|
||||
func (o Object) Set(name string, value interface{}) error {
|
||||
val, err := o.object.runtime.safeToValue(value)
|
||||
if err != nil {
|
||||
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.
|
||||
//
|
||||
// Equivalent to calling Object.keys on the object.
|
||||
func (self Object) Keys() []string {
|
||||
func (o Object) 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)
|
||||
return true
|
||||
})
|
||||
|
@ -730,10 +717,10 @@ func (self Object) Keys() []string {
|
|||
|
||||
// KeysByParent gets the keys (and those of the parents) for the given object,
|
||||
// in order of "closest" to "furthest".
|
||||
func (self Object) KeysByParent() [][]string {
|
||||
func (o Object) KeysByParent() [][]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
|
||||
|
||||
o.enumerate(false, func(name string) bool {
|
||||
|
@ -759,28 +746,29 @@ func (self Object) KeysByParent() [][]string {
|
|||
// Boolean
|
||||
// Date
|
||||
// RegExp
|
||||
func (self Object) Class() string {
|
||||
return self.object.class
|
||||
func (o Object) Class() string {
|
||||
return o.object.class
|
||||
}
|
||||
|
||||
func (self Object) MarshalJSON() ([]byte, error) {
|
||||
// MarshalJSON implements json.Marshaller.
|
||||
func (o Object) MarshalJSON() ([]byte, error) {
|
||||
var goValue interface{}
|
||||
switch value := self.object.value.(type) {
|
||||
case *_goStructObject:
|
||||
switch value := o.object.value.(type) {
|
||||
case *goStructObject:
|
||||
goValue = value.value.Interface()
|
||||
case *_goMapObject:
|
||||
case *goMapObject:
|
||||
goValue = value.value.Interface()
|
||||
case *_goArrayObject:
|
||||
case *goArrayObject:
|
||||
goValue = value.value.Interface()
|
||||
case *_goSliceObject:
|
||||
case *goSliceObject:
|
||||
goValue = value.value.Interface()
|
||||
default:
|
||||
// It's a JS object; pass it to JSON.stringify:
|
||||
var result []byte
|
||||
err := catchPanic(func() {
|
||||
resultVal := builtinJSON_stringify(FunctionCall{
|
||||
runtime: self.object.runtime,
|
||||
ArgumentList: []Value{self.value},
|
||||
resultVal := builtinJSONStringify(FunctionCall{
|
||||
runtime: o.object.runtime,
|
||||
ArgumentList: []Value{o.value},
|
||||
})
|
||||
result = []byte(resultVal.String())
|
||||
})
|
||||
|
|
32
v1/vendor/github.com/robertkrimen/otto/otto_.go
generated
vendored
|
@ -3,28 +3,28 @@ package otto
|
|||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
runtime_ "runtime"
|
||||
goruntime "runtime"
|
||||
"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 {
|
||||
return isIdentifier_Regexp.MatchString(string_)
|
||||
func isIdentifier(value string) bool {
|
||||
return isIdentifierRegexp.MatchString(value)
|
||||
}
|
||||
|
||||
func (self *_runtime) toValueArray(arguments ...interface{}) []Value {
|
||||
func (rt *runtime) toValueArray(arguments ...interface{}) []Value {
|
||||
length := len(arguments)
|
||||
if length == 1 {
|
||||
if valueArray, ok := arguments[0].([]Value); ok {
|
||||
return valueArray
|
||||
}
|
||||
return []Value{self.toValue(arguments[0])}
|
||||
return []Value{rt.toValue(arguments[0])}
|
||||
}
|
||||
|
||||
valueArray := make([]Value, length)
|
||||
for index, value := range arguments {
|
||||
valueArray[index] = self.toValue(value)
|
||||
valueArray[index] = rt.toValue(value)
|
||||
}
|
||||
|
||||
return valueArray
|
||||
|
@ -89,15 +89,13 @@ func valueToRangeIndex(indexValue Value, length int64, negativeIsZero bool) int6
|
|||
if index < 0 {
|
||||
index = 0
|
||||
}
|
||||
} else {
|
||||
if index > length {
|
||||
} else if index > length {
|
||||
index = length
|
||||
}
|
||||
}
|
||||
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)
|
||||
if len(array) == 1 {
|
||||
// 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
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
// Assume the second argument is missing or undefined
|
||||
length = int64(size)
|
||||
length = size
|
||||
if len(source) == 1 {
|
||||
// If there is only the start argument, then length = size
|
||||
return
|
||||
return start, length
|
||||
}
|
||||
|
||||
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
|
||||
length = lengthValue.number().int64
|
||||
}
|
||||
return
|
||||
return start, length
|
||||
}
|
||||
|
||||
func hereBeDragons(arguments ...interface{}) string {
|
||||
pc, _, _, _ := runtime_.Caller(1) //nolint: dogsled
|
||||
name := runtime_.FuncForPC(pc).Name()
|
||||
pc, _, _, _ := goruntime.Caller(1) //nolint: dogsled
|
||||
name := goruntime.FuncForPC(pc).Name()
|
||||
message := fmt.Sprintf("Here be dragons -- %s", name)
|
||||
if len(arguments) > 0 {
|
||||
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 (
|
||||
err_UnexpectedToken = "Unexpected token %v"
|
||||
err_UnexpectedEndOfInput = "Unexpected end of input"
|
||||
errUnexpectedToken = "Unexpected token %v"
|
||||
errUnexpectedEndOfInput = "Unexpected end of input"
|
||||
)
|
||||
|
||||
// UnexpectedNumber: 'Unexpected number',
|
||||
|
@ -20,7 +20,7 @@ const (
|
|||
// NewlineAfterThrow: 'Illegal newline after throw',
|
||||
// InvalidRegExp: 'Invalid regular expression',
|
||||
// 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',
|
||||
// MultipleDefaultsInSwitch: 'More than one default clause in switch statement',
|
||||
// NoCatchOrFinally: 'Missing catch or finally after try',
|
||||
|
@ -55,27 +55,27 @@ type Error struct {
|
|||
|
||||
// FIXME Should this be "SyntaxError"?
|
||||
|
||||
func (self Error) Error() string {
|
||||
filename := self.Position.Filename
|
||||
func (e Error) Error() string {
|
||||
filename := e.Position.Filename
|
||||
if filename == "" {
|
||||
filename = "(anonymous)"
|
||||
}
|
||||
return fmt.Sprintf("%s: Line %d:%d %s",
|
||||
filename,
|
||||
self.Position.Line,
|
||||
self.Position.Column,
|
||||
self.Message,
|
||||
e.Position.Line,
|
||||
e.Position.Column,
|
||||
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
|
||||
switch place := place.(type) {
|
||||
case int:
|
||||
idx = self.idxOf(place)
|
||||
idx = p.idxOf(place)
|
||||
case file.Idx:
|
||||
if place == 0 {
|
||||
idx = self.idxOf(self.chrOffset)
|
||||
idx = p.idxOf(p.chrOffset)
|
||||
} else {
|
||||
idx = place
|
||||
}
|
||||
|
@ -83,57 +83,69 @@ func (self *_parser) error(place interface{}, msg string, msgValues ...interface
|
|||
panic(fmt.Errorf("error(%T, ...)", place))
|
||||
}
|
||||
|
||||
position := self.position(idx)
|
||||
position := p.position(idx)
|
||||
msg = fmt.Sprintf(msg, msgValues...)
|
||||
self.errors.Add(position, msg)
|
||||
return self.errors[len(self.errors)-1]
|
||||
p.errors.Add(position, msg)
|
||||
}
|
||||
|
||||
func (self *_parser) errorUnexpected(idx file.Idx, chr rune) error {
|
||||
func (p *parser) errorUnexpected(idx file.Idx, chr rune) {
|
||||
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 {
|
||||
switch tkn {
|
||||
case token.EOF:
|
||||
return self.error(file.Idx(0), err_UnexpectedEndOfInput)
|
||||
func (p *parser) errorUnexpectedToken(tkn token.Token) {
|
||||
if tkn == token.EOF {
|
||||
p.error(file.Idx(0), errUnexpectedEndOfInput)
|
||||
return
|
||||
}
|
||||
value := tkn.String()
|
||||
switch tkn {
|
||||
case token.BOOLEAN, token.NULL:
|
||||
value = self.literal
|
||||
p.error(p.idx, errUnexpectedToken, p.literal)
|
||||
case token.IDENTIFIER:
|
||||
return self.error(self.idx, "Unexpected identifier")
|
||||
p.error(p.idx, "Unexpected identifier")
|
||||
case token.KEYWORD:
|
||||
// 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:
|
||||
return self.error(self.idx, "Unexpected number")
|
||||
p.error(p.idx, "Unexpected number")
|
||||
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.
|
||||
type ErrorList []*Error //nolint: errname
|
||||
|
||||
// Add adds an Error with given position and message to an ErrorList.
|
||||
func (self *ErrorList) Add(position file.Position, msg string) {
|
||||
*self = append(*self, &Error{position, msg})
|
||||
func (el *ErrorList) Add(position file.Position, msg string) {
|
||||
*el = append(*el, &Error{position, msg})
|
||||
}
|
||||
|
||||
// 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) }
|
||||
func (self ErrorList) Swap(i, j int) { self[i], self[j] = self[j], self[i] }
|
||||
func (self ErrorList) Less(i, j int) bool {
|
||||
x := &self[i].Position
|
||||
y := &self[j].Position
|
||||
// Len implement sort.Interface.
|
||||
func (el *ErrorList) Len() int {
|
||||
return len(*el)
|
||||
}
|
||||
|
||||
// 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 {
|
||||
return true
|
||||
}
|
||||
|
@ -148,26 +160,28 @@ func (self ErrorList) Less(i, j int) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func (self ErrorList) Sort() {
|
||||
sort.Sort(self)
|
||||
// Sort sorts el.
|
||||
func (el *ErrorList) Sort() {
|
||||
sort.Sort(el)
|
||||
}
|
||||
|
||||
// Error implements the Error interface.
|
||||
func (self ErrorList) Error() string {
|
||||
switch len(self) {
|
||||
func (el *ErrorList) Error() string {
|
||||
switch len(*el) {
|
||||
case 0:
|
||||
return "no errors"
|
||||
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.
|
||||
// If the list is empty, Err returns nil.
|
||||
func (self ErrorList) Err() error {
|
||||
if len(self) == 0 {
|
||||
func (el *ErrorList) Err() error {
|
||||
if len(*el) == 0 {
|
||||
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"
|
||||
)
|
||||
|
||||
type _chr struct {
|
||||
type chr struct { //nolint: unused
|
||||
value rune
|
||||
width int
|
||||
}
|
||||
|
@ -55,49 +55,50 @@ func isIdentifierPart(chr rune) bool {
|
|||
chr >= utf8.RuneSelf && (unicode.IsLetter(chr) || unicode.IsDigit(chr))
|
||||
}
|
||||
|
||||
func (self *_parser) scanIdentifier() (string, error) {
|
||||
offset := self.chrOffset
|
||||
func (p *parser) scanIdentifier() (string, error) {
|
||||
offset := p.chrOffset
|
||||
parse := false
|
||||
for isIdentifierPart(self.chr) {
|
||||
if self.chr == '\\' {
|
||||
distance := self.chrOffset - offset
|
||||
self.read()
|
||||
if self.chr != 'u' {
|
||||
return "", fmt.Errorf("Invalid identifier escape character: %c (%s)", self.chr, string(self.chr))
|
||||
for isIdentifierPart(p.chr) {
|
||||
if p.chr == '\\' {
|
||||
distance := p.chrOffset - offset
|
||||
p.read()
|
||||
if p.chr != 'u' {
|
||||
return "", fmt.Errorf("invalid identifier escape character: %c (%s)", p.chr, string(p.chr))
|
||||
}
|
||||
parse = true
|
||||
var value rune
|
||||
for j := 0; j < 4; j++ {
|
||||
self.read()
|
||||
decimal, ok := hex2decimal(byte(self.chr))
|
||||
p.read()
|
||||
decimal, ok := hex2decimal(byte(p.chr))
|
||||
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
|
||||
}
|
||||
if value == '\\' {
|
||||
return "", fmt.Errorf("Invalid identifier escape value: %c (%s)", value, string(value))
|
||||
} else if distance == 0 {
|
||||
switch {
|
||||
case value == '\\':
|
||||
return "", fmt.Errorf("invalid identifier escape value: %c (%s)", value, string(value))
|
||||
case distance == 0:
|
||||
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) {
|
||||
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 {
|
||||
return parseStringLiteral(literal)
|
||||
}
|
||||
return literal, nil
|
||||
}
|
||||
|
||||
// 7.2
|
||||
func isLineWhiteSpace(chr rune) bool {
|
||||
// 7.2.
|
||||
func isLineWhiteSpace(chr rune) bool { //nolint: unused, deadcode
|
||||
switch chr {
|
||||
case '\u0009', '\u000b', '\u000c', '\u0020', '\u00a0', '\ufeff':
|
||||
return true
|
||||
|
@ -109,7 +110,7 @@ func isLineWhiteSpace(chr rune) bool {
|
|||
return unicode.IsSpace(chr)
|
||||
}
|
||||
|
||||
// 7.3
|
||||
// 7.3.
|
||||
func isLineTerminator(chr rune) bool {
|
||||
switch chr {
|
||||
case '\u000a', '\u000d', '\u2028', '\u2029':
|
||||
|
@ -118,19 +119,19 @@ func isLineTerminator(chr rune) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func (self *_parser) scan() (tkn token.Token, literal string, idx file.Idx) {
|
||||
self.implicitSemicolon = false
|
||||
func (p *parser) scan() (tkn token.Token, literal string, idx file.Idx) { //nolint: nonamedreturns
|
||||
p.implicitSemicolon = false
|
||||
|
||||
for {
|
||||
self.skipWhiteSpace()
|
||||
p.skipWhiteSpace()
|
||||
|
||||
idx = self.idxOf(self.chrOffset)
|
||||
idx = p.idxOf(p.chrOffset)
|
||||
insertSemicolon := false
|
||||
|
||||
switch chr := self.chr; {
|
||||
switch chr := p.chr; {
|
||||
case isIdentifierStart(chr):
|
||||
var err error
|
||||
literal, err = self.scanIdentifier()
|
||||
literal, err = p.scanIdentifier()
|
||||
if err != nil {
|
||||
tkn = token.ILLEGAL
|
||||
break
|
||||
|
@ -142,23 +143,20 @@ func (self *_parser) scan() (tkn token.Token, literal string, idx file.Idx) {
|
|||
|
||||
switch tkn {
|
||||
case 0: // Not a keyword
|
||||
if literal == "true" || literal == "false" {
|
||||
self.insertSemicolon = true
|
||||
tkn = token.BOOLEAN
|
||||
return
|
||||
} else if literal == "null" {
|
||||
self.insertSemicolon = true
|
||||
tkn = token.NULL
|
||||
return
|
||||
switch literal {
|
||||
case "true", "false":
|
||||
p.insertSemicolon = true
|
||||
return token.BOOLEAN, literal, idx
|
||||
case "null":
|
||||
p.insertSemicolon = true
|
||||
return token.NULL, literal, idx
|
||||
}
|
||||
|
||||
case token.KEYWORD:
|
||||
tkn = token.KEYWORD
|
||||
if strict {
|
||||
// TODO If strict and in strict mode, then this is not a break
|
||||
break
|
||||
}
|
||||
return
|
||||
return token.KEYWORD, literal, idx
|
||||
|
||||
case
|
||||
token.THIS,
|
||||
|
@ -167,40 +165,39 @@ func (self *_parser) scan() (tkn token.Token, literal string, idx file.Idx) {
|
|||
token.RETURN,
|
||||
token.CONTINUE,
|
||||
token.DEBUGGER:
|
||||
self.insertSemicolon = true
|
||||
return
|
||||
p.insertSemicolon = true
|
||||
return tkn, literal, idx
|
||||
|
||||
default:
|
||||
return
|
||||
return tkn, literal, idx
|
||||
}
|
||||
}
|
||||
self.insertSemicolon = true
|
||||
tkn = token.IDENTIFIER
|
||||
return
|
||||
p.insertSemicolon = true
|
||||
return token.IDENTIFIER, literal, idx
|
||||
case '0' <= chr && chr <= '9':
|
||||
self.insertSemicolon = true
|
||||
tkn, literal = self.scanNumericLiteral(false)
|
||||
return
|
||||
p.insertSemicolon = true
|
||||
tkn, literal = p.scanNumericLiteral(false)
|
||||
return tkn, literal, idx
|
||||
default:
|
||||
self.read()
|
||||
p.read()
|
||||
switch chr {
|
||||
case -1:
|
||||
if self.insertSemicolon {
|
||||
self.insertSemicolon = false
|
||||
self.implicitSemicolon = true
|
||||
if p.insertSemicolon {
|
||||
p.insertSemicolon = false
|
||||
p.implicitSemicolon = true
|
||||
}
|
||||
tkn = token.EOF
|
||||
case '\r', '\n', '\u2028', '\u2029':
|
||||
self.insertSemicolon = false
|
||||
self.implicitSemicolon = true
|
||||
self.comments.AtLineBreak()
|
||||
p.insertSemicolon = false
|
||||
p.implicitSemicolon = true
|
||||
p.comments.AtLineBreak()
|
||||
continue
|
||||
case ':':
|
||||
tkn = token.COLON
|
||||
case '.':
|
||||
if digitValue(self.chr) < 10 {
|
||||
if digitValue(p.chr) < 10 {
|
||||
insertSemicolon = true
|
||||
tkn, literal = self.scanNumericLiteral(true)
|
||||
tkn, literal = p.scanNumericLiteral(true)
|
||||
} else {
|
||||
tkn = token.PERIOD
|
||||
}
|
||||
|
@ -224,68 +221,69 @@ func (self *_parser) scan() (tkn token.Token, literal string, idx file.Idx) {
|
|||
tkn = token.RIGHT_BRACE
|
||||
insertSemicolon = true
|
||||
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 {
|
||||
insertSemicolon = true
|
||||
}
|
||||
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 {
|
||||
insertSemicolon = true
|
||||
}
|
||||
case '*':
|
||||
tkn = self.switch2(token.MULTIPLY, token.MULTIPLY_ASSIGN)
|
||||
tkn = p.switch2(token.MULTIPLY, token.MULTIPLY_ASSIGN)
|
||||
case '/':
|
||||
if self.chr == '/' {
|
||||
if self.mode&StoreComments != 0 {
|
||||
literal := string(self.readSingleLineComment())
|
||||
self.comments.AddComment(ast.NewComment(literal, self.idx))
|
||||
switch p.chr {
|
||||
case '/':
|
||||
if p.mode&StoreComments != 0 {
|
||||
literal := string(p.readSingleLineComment())
|
||||
p.comments.AddComment(ast.NewComment(literal, idx))
|
||||
continue
|
||||
}
|
||||
self.skipSingleLineComment()
|
||||
p.skipSingleLineComment()
|
||||
continue
|
||||
} else if self.chr == '*' {
|
||||
if self.mode&StoreComments != 0 {
|
||||
literal = string(self.readMultiLineComment())
|
||||
self.comments.AddComment(ast.NewComment(literal, self.idx))
|
||||
case '*':
|
||||
if p.mode&StoreComments != 0 {
|
||||
literal = string(p.readMultiLineComment())
|
||||
p.comments.AddComment(ast.NewComment(literal, idx))
|
||||
continue
|
||||
}
|
||||
self.skipMultiLineComment()
|
||||
p.skipMultiLineComment()
|
||||
continue
|
||||
} else {
|
||||
default:
|
||||
// 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
|
||||
}
|
||||
case '%':
|
||||
tkn = self.switch2(token.REMAINDER, token.REMAINDER_ASSIGN)
|
||||
tkn = p.switch2(token.REMAINDER, token.REMAINDER_ASSIGN)
|
||||
case '^':
|
||||
tkn = self.switch2(token.EXCLUSIVE_OR, token.EXCLUSIVE_OR_ASSIGN)
|
||||
tkn = p.switch2(token.EXCLUSIVE_OR, token.EXCLUSIVE_OR_ASSIGN)
|
||||
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 '>':
|
||||
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 '=':
|
||||
tkn = self.switch2(token.ASSIGN, token.EQUAL)
|
||||
if tkn == token.EQUAL && self.chr == '=' {
|
||||
self.read()
|
||||
tkn = p.switch2(token.ASSIGN, token.EQUAL)
|
||||
if tkn == token.EQUAL && p.chr == '=' {
|
||||
p.read()
|
||||
tkn = token.STRICT_EQUAL
|
||||
}
|
||||
case '!':
|
||||
tkn = self.switch2(token.NOT, token.NOT_EQUAL)
|
||||
if tkn == token.NOT_EQUAL && self.chr == '=' {
|
||||
self.read()
|
||||
tkn = p.switch2(token.NOT, token.NOT_EQUAL)
|
||||
if tkn == token.NOT_EQUAL && p.chr == '=' {
|
||||
p.read()
|
||||
tkn = token.STRICT_NOT_EQUAL
|
||||
}
|
||||
case '&':
|
||||
if self.chr == '^' {
|
||||
self.read()
|
||||
tkn = self.switch2(token.AND_NOT, token.AND_NOT_ASSIGN)
|
||||
if p.chr == '^' {
|
||||
p.read()
|
||||
tkn = p.switch2(token.AND_NOT, token.AND_NOT_ASSIGN)
|
||||
} else {
|
||||
tkn = self.switch3(token.AND, token.AND_ASSIGN, '&', token.LOGICAL_AND)
|
||||
tkn = p.switch3(token.AND, token.AND_ASSIGN, '&', token.LOGICAL_AND)
|
||||
}
|
||||
case '|':
|
||||
tkn = self.switch3(token.OR, token.OR_ASSIGN, '|', token.LOGICAL_OR)
|
||||
tkn = p.switch3(token.OR, token.OR_ASSIGN, '|', token.LOGICAL_OR)
|
||||
case '~':
|
||||
tkn = token.BITWISE_NOT
|
||||
case '?':
|
||||
|
@ -294,49 +292,49 @@ func (self *_parser) scan() (tkn token.Token, literal string, idx file.Idx) {
|
|||
insertSemicolon = true
|
||||
tkn = token.STRING
|
||||
var err error
|
||||
literal, err = self.scanString(self.chrOffset - 1)
|
||||
literal, err = p.scanString(p.chrOffset - 1)
|
||||
if err != nil {
|
||||
tkn = token.ILLEGAL
|
||||
}
|
||||
default:
|
||||
self.errorUnexpected(idx, chr)
|
||||
p.errorUnexpected(idx, chr)
|
||||
tkn = token.ILLEGAL
|
||||
}
|
||||
}
|
||||
self.insertSemicolon = insertSemicolon
|
||||
return
|
||||
p.insertSemicolon = insertSemicolon
|
||||
return tkn, literal, idx
|
||||
}
|
||||
}
|
||||
|
||||
func (self *_parser) switch2(tkn0, tkn1 token.Token) token.Token {
|
||||
if self.chr == '=' {
|
||||
self.read()
|
||||
func (p *parser) switch2(tkn0, tkn1 token.Token) token.Token {
|
||||
if p.chr == '=' {
|
||||
p.read()
|
||||
return tkn1
|
||||
}
|
||||
return tkn0
|
||||
}
|
||||
|
||||
func (self *_parser) switch3(tkn0, tkn1 token.Token, chr2 rune, tkn2 token.Token) token.Token {
|
||||
if self.chr == '=' {
|
||||
self.read()
|
||||
func (p *parser) switch3(tkn0, tkn1 token.Token, chr2 rune, tkn2 token.Token) token.Token {
|
||||
if p.chr == '=' {
|
||||
p.read()
|
||||
return tkn1
|
||||
}
|
||||
if self.chr == chr2 {
|
||||
self.read()
|
||||
if p.chr == chr2 {
|
||||
p.read()
|
||||
return tkn2
|
||||
}
|
||||
return tkn0
|
||||
}
|
||||
|
||||
func (self *_parser) switch4(tkn0, tkn1 token.Token, chr2 rune, tkn2, tkn3 token.Token) token.Token {
|
||||
if self.chr == '=' {
|
||||
self.read()
|
||||
func (p *parser) switch4(tkn0, tkn1 token.Token, chr2 rune, tkn2, tkn3 token.Token) token.Token {
|
||||
if p.chr == '=' {
|
||||
p.read()
|
||||
return tkn1
|
||||
}
|
||||
if self.chr == chr2 {
|
||||
self.read()
|
||||
if self.chr == '=' {
|
||||
self.read()
|
||||
if p.chr == chr2 {
|
||||
p.read()
|
||||
if p.chr == '=' {
|
||||
p.read()
|
||||
return tkn3
|
||||
}
|
||||
return tkn2
|
||||
|
@ -344,21 +342,21 @@ func (self *_parser) switch4(tkn0, tkn1 token.Token, chr2 rune, tkn2, tkn3 token
|
|||
return tkn0
|
||||
}
|
||||
|
||||
func (self *_parser) switch6(tkn0, tkn1 token.Token, chr2 rune, tkn2, tkn3 token.Token, chr3 rune, tkn4, tkn5 token.Token) token.Token {
|
||||
if self.chr == '=' {
|
||||
self.read()
|
||||
func (p *parser) switch6(tkn0, tkn1 token.Token, chr2 rune, tkn2, tkn3 token.Token, chr3 rune, tkn4, tkn5 token.Token) token.Token {
|
||||
if p.chr == '=' {
|
||||
p.read()
|
||||
return tkn1
|
||||
}
|
||||
if self.chr == chr2 {
|
||||
self.read()
|
||||
if self.chr == '=' {
|
||||
self.read()
|
||||
if p.chr == chr2 {
|
||||
p.read()
|
||||
if p.chr == '=' {
|
||||
p.read()
|
||||
return tkn3
|
||||
}
|
||||
if self.chr == chr3 {
|
||||
self.read()
|
||||
if self.chr == '=' {
|
||||
self.read()
|
||||
if p.chr == chr3 {
|
||||
p.read()
|
||||
if p.chr == '=' {
|
||||
p.read()
|
||||
return tkn5
|
||||
}
|
||||
return tkn4
|
||||
|
@ -368,137 +366,137 @@ func (self *_parser) switch6(tkn0, tkn1 token.Token, chr2 rune, tkn2, tkn3 token
|
|||
return tkn0
|
||||
}
|
||||
|
||||
func (self *_parser) chrAt(index int) _chr {
|
||||
value, width := utf8.DecodeRuneInString(self.str[index:])
|
||||
return _chr{
|
||||
func (p *parser) chrAt(index int) chr { //nolint: unused
|
||||
value, width := utf8.DecodeRuneInString(p.str[index:])
|
||||
return chr{
|
||||
value: value,
|
||||
width: width,
|
||||
}
|
||||
}
|
||||
|
||||
func (self *_parser) _peek() rune {
|
||||
if self.offset+1 < self.length {
|
||||
return rune(self.str[self.offset+1])
|
||||
func (p *parser) peek() rune {
|
||||
if p.offset+1 < p.length {
|
||||
return rune(p.str[p.offset+1])
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
func (self *_parser) read() {
|
||||
if self.offset < self.length {
|
||||
self.chrOffset = self.offset
|
||||
chr, width := rune(self.str[self.offset]), 1
|
||||
func (p *parser) read() {
|
||||
if p.offset < p.length {
|
||||
p.chrOffset = p.offset
|
||||
chr, width := rune(p.str[p.offset]), 1
|
||||
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 {
|
||||
self.error(self.chrOffset, "Invalid UTF-8 character")
|
||||
p.error(p.chrOffset, "Invalid UTF-8 character")
|
||||
}
|
||||
}
|
||||
self.offset += width
|
||||
self.chr = chr
|
||||
p.offset += width
|
||||
p.chr = chr
|
||||
} else {
|
||||
self.chrOffset = self.length
|
||||
self.chr = -1 // EOF
|
||||
p.chrOffset = p.length
|
||||
p.chr = -1 // EOF
|
||||
}
|
||||
}
|
||||
|
||||
// This is here since the functions are so similar
|
||||
func (self *_RegExp_parser) read() {
|
||||
if self.offset < self.length {
|
||||
self.chrOffset = self.offset
|
||||
chr, width := rune(self.str[self.offset]), 1
|
||||
// This is here since the functions are so similar.
|
||||
func (p *regExpParser) read() {
|
||||
if p.offset < p.length {
|
||||
p.chrOffset = p.offset
|
||||
chr, width := rune(p.str[p.offset]), 1
|
||||
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 {
|
||||
self.error(self.chrOffset, "Invalid UTF-8 character")
|
||||
p.error(p.chrOffset, "Invalid UTF-8 character")
|
||||
}
|
||||
}
|
||||
self.offset += width
|
||||
self.chr = chr
|
||||
p.offset += width
|
||||
p.chr = chr
|
||||
} else {
|
||||
self.chrOffset = self.length
|
||||
self.chr = -1 // EOF
|
||||
p.chrOffset = p.length
|
||||
p.chr = -1 // EOF
|
||||
}
|
||||
}
|
||||
|
||||
func (self *_parser) readSingleLineComment() (result []rune) {
|
||||
for self.chr != -1 {
|
||||
self.read()
|
||||
if isLineTerminator(self.chr) {
|
||||
return
|
||||
func (p *parser) readSingleLineComment() []rune {
|
||||
var result []rune
|
||||
for p.chr != -1 {
|
||||
p.read()
|
||||
if isLineTerminator(p.chr) {
|
||||
return result
|
||||
}
|
||||
result = append(result, self.chr)
|
||||
result = append(result, p.chr)
|
||||
}
|
||||
|
||||
// Get rid of the trailing -1
|
||||
result = result[:len(result)-1]
|
||||
|
||||
return
|
||||
return result[:len(result)-1]
|
||||
}
|
||||
|
||||
func (self *_parser) readMultiLineComment() (result []rune) {
|
||||
self.read()
|
||||
for self.chr >= 0 {
|
||||
chr := self.chr
|
||||
self.read()
|
||||
if chr == '*' && self.chr == '/' {
|
||||
self.read()
|
||||
return
|
||||
func (p *parser) readMultiLineComment() []rune {
|
||||
var result []rune
|
||||
p.read()
|
||||
for p.chr >= 0 {
|
||||
chr := p.chr
|
||||
p.read()
|
||||
if chr == '*' && p.chr == '/' {
|
||||
p.read()
|
||||
return result
|
||||
}
|
||||
|
||||
result = append(result, chr)
|
||||
}
|
||||
|
||||
self.errorUnexpected(0, self.chr)
|
||||
p.errorUnexpected(0, p.chr)
|
||||
|
||||
return
|
||||
return result
|
||||
}
|
||||
|
||||
func (self *_parser) skipSingleLineComment() {
|
||||
for self.chr != -1 {
|
||||
self.read()
|
||||
if isLineTerminator(self.chr) {
|
||||
func (p *parser) skipSingleLineComment() {
|
||||
for p.chr != -1 {
|
||||
p.read()
|
||||
if isLineTerminator(p.chr) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (self *_parser) skipMultiLineComment() {
|
||||
self.read()
|
||||
for self.chr >= 0 {
|
||||
chr := self.chr
|
||||
self.read()
|
||||
if chr == '*' && self.chr == '/' {
|
||||
self.read()
|
||||
func (p *parser) skipMultiLineComment() {
|
||||
p.read()
|
||||
for p.chr >= 0 {
|
||||
chr := p.chr
|
||||
p.read()
|
||||
if chr == '*' && p.chr == '/' {
|
||||
p.read()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
self.errorUnexpected(0, self.chr)
|
||||
p.errorUnexpected(0, p.chr)
|
||||
}
|
||||
|
||||
func (self *_parser) skipWhiteSpace() {
|
||||
func (p *parser) skipWhiteSpace() {
|
||||
for {
|
||||
switch self.chr {
|
||||
switch p.chr {
|
||||
case ' ', '\t', '\f', '\v', '\u00a0', '\ufeff':
|
||||
self.read()
|
||||
p.read()
|
||||
continue
|
||||
case '\r':
|
||||
if self._peek() == '\n' {
|
||||
self.comments.AtLineBreak()
|
||||
self.read()
|
||||
if p.peek() == '\n' {
|
||||
p.comments.AtLineBreak()
|
||||
p.read()
|
||||
}
|
||||
fallthrough
|
||||
case '\u2028', '\u2029', '\n':
|
||||
if self.insertSemicolon {
|
||||
if p.insertSemicolon {
|
||||
return
|
||||
}
|
||||
self.comments.AtLineBreak()
|
||||
self.read()
|
||||
p.comments.AtLineBreak()
|
||||
p.read()
|
||||
continue
|
||||
}
|
||||
if self.chr >= utf8.RuneSelf {
|
||||
if unicode.IsSpace(self.chr) {
|
||||
self.read()
|
||||
if p.chr >= utf8.RuneSelf {
|
||||
if unicode.IsSpace(p.chr) {
|
||||
p.read()
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
@ -506,121 +504,114 @@ func (self *_parser) skipWhiteSpace() {
|
|||
}
|
||||
}
|
||||
|
||||
func (self *_parser) skipLineWhiteSpace() {
|
||||
for isLineWhiteSpace(self.chr) {
|
||||
self.read()
|
||||
func (p *parser) scanMantissa(base int) {
|
||||
for digitValue(p.chr) < base {
|
||||
p.read()
|
||||
}
|
||||
}
|
||||
|
||||
func (self *_parser) scanMantissa(base int) {
|
||||
for digitValue(self.chr) < base {
|
||||
self.read()
|
||||
}
|
||||
}
|
||||
|
||||
func (self *_parser) scanEscape(quote rune) {
|
||||
func (p *parser) scanEscape(quote rune) {
|
||||
var length, base uint32
|
||||
switch self.chr {
|
||||
//case '0', '1', '2', '3', '4', '5', '6', '7':
|
||||
switch p.chr {
|
||||
// Octal:
|
||||
// length, base, limit = 3, 8, 255
|
||||
case 'a', 'b', 'f', 'n', 'r', 't', 'v', '\\', '"', '\'', '0':
|
||||
self.read()
|
||||
p.read()
|
||||
return
|
||||
case '\r', '\n', '\u2028', '\u2029':
|
||||
self.scanNewline()
|
||||
p.scanNewline()
|
||||
return
|
||||
case 'x':
|
||||
self.read()
|
||||
p.read()
|
||||
length, base = 2, 16
|
||||
case 'u':
|
||||
self.read()
|
||||
p.read()
|
||||
length, base = 4, 16
|
||||
default:
|
||||
self.read() // Always make progress
|
||||
p.read() // Always make progress
|
||||
return
|
||||
}
|
||||
|
||||
var value uint32
|
||||
for ; length > 0 && self.chr != quote && self.chr >= 0; length-- {
|
||||
digit := uint32(digitValue(self.chr))
|
||||
for ; length > 0 && p.chr != quote && p.chr >= 0; length-- {
|
||||
digit := uint32(digitValue(p.chr))
|
||||
if digit >= base {
|
||||
break
|
||||
}
|
||||
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 {
|
||||
chr := self.chr
|
||||
for p.chr != quote {
|
||||
chr := p.chr
|
||||
if chr == '\n' || chr == '\r' || chr == '\u2028' || chr == '\u2029' || chr < 0 {
|
||||
goto newline
|
||||
}
|
||||
self.read()
|
||||
if chr == '\\' {
|
||||
p.read()
|
||||
switch {
|
||||
case chr == '\\':
|
||||
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
|
||||
}
|
||||
self.read()
|
||||
p.read()
|
||||
} else {
|
||||
self.scanEscape(quote)
|
||||
p.scanEscape(quote)
|
||||
}
|
||||
} else if chr == '[' && quote == '/' {
|
||||
case chr == '[' && quote == '/':
|
||||
// Allow a slash (/) in a bracket character class ([...])
|
||||
// TODO Fix this, this is hacky...
|
||||
quote = -1
|
||||
} else if chr == ']' && quote == -1 {
|
||||
case chr == ']' && quote == -1:
|
||||
quote = '/'
|
||||
}
|
||||
}
|
||||
|
||||
// " ' /
|
||||
self.read()
|
||||
p.read()
|
||||
|
||||
return string(self.str[offset:self.chrOffset]), nil
|
||||
return p.str[offset:p.chrOffset], nil
|
||||
|
||||
newline:
|
||||
self.scanNewline()
|
||||
p.scanNewline()
|
||||
err := "String not terminated"
|
||||
if quote == '/' {
|
||||
err = "Invalid regular expression: missing /"
|
||||
self.error(self.idxOf(offset), err)
|
||||
p.error(p.idxOf(offset), err)
|
||||
}
|
||||
return "", errors.New(err)
|
||||
}
|
||||
|
||||
func (self *_parser) scanNewline() {
|
||||
if self.chr == '\r' {
|
||||
self.read()
|
||||
if self.chr != '\n' {
|
||||
func (p *parser) scanNewline() {
|
||||
if p.chr == '\r' {
|
||||
p.read()
|
||||
if p.chr != '\n' {
|
||||
return
|
||||
}
|
||||
}
|
||||
self.read()
|
||||
p.read()
|
||||
}
|
||||
|
||||
func hex2decimal(chr byte) (value rune, ok bool) {
|
||||
{
|
||||
chr := rune(chr)
|
||||
func hex2decimal(chr byte) (rune, bool) {
|
||||
r := rune(chr)
|
||||
switch {
|
||||
case '0' <= chr && chr <= '9':
|
||||
return chr - '0', true
|
||||
case 'a' <= chr && chr <= 'f':
|
||||
return chr - 'a' + 10, true
|
||||
case 'A' <= chr && chr <= 'F':
|
||||
return chr - 'A' + 10, true
|
||||
}
|
||||
return
|
||||
case '0' <= r && r <= '9':
|
||||
return r - '0', true
|
||||
case 'a' <= r && r <= 'f':
|
||||
return r - 'a' + 10, true
|
||||
case 'A' <= r && r <= 'F':
|
||||
return r - 'A' + 10, true
|
||||
default:
|
||||
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
|
||||
value, err = strconv.ParseInt(literal, 0, 64)
|
||||
if err == nil {
|
||||
|
@ -632,14 +623,16 @@ func parseNumberLiteral(literal string) (value interface{}, err error) {
|
|||
value, err = strconv.ParseFloat(literal, 64)
|
||||
if err == nil {
|
||||
return value, nil
|
||||
} else if err.(*strconv.NumError).Err == strconv.ErrRange {
|
||||
} else if errors.Is(err, strconv.ErrRange) {
|
||||
// Infinity, etc.
|
||||
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
|
||||
|
||||
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') {
|
||||
// Could just be a very large number (e.g. 0x8000000000000000)
|
||||
var value float64
|
||||
|
@ -647,7 +640,7 @@ func parseNumberLiteral(literal string) (value interface{}, err error) {
|
|||
for _, chr := range literal {
|
||||
digit := digitValue(chr)
|
||||
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)
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -783,78 +776,79 @@ func parseStringLiteral(literal string) (string, error) {
|
|||
return buffer.String(), nil
|
||||
}
|
||||
|
||||
func (self *_parser) scanNumericLiteral(decimalPoint bool) (token.Token, string) {
|
||||
offset := self.chrOffset
|
||||
func (p *parser) scanNumericLiteral(decimalPoint bool) (token.Token, string) {
|
||||
offset := p.chrOffset
|
||||
tkn := token.NUMBER
|
||||
|
||||
if decimalPoint {
|
||||
offset--
|
||||
self.scanMantissa(10)
|
||||
p.scanMantissa(10)
|
||||
goto exponent
|
||||
}
|
||||
|
||||
if self.chr == '0' {
|
||||
offset := self.chrOffset
|
||||
self.read()
|
||||
if self.chr == 'x' || self.chr == 'X' {
|
||||
if p.chr == '0' {
|
||||
offset := p.chrOffset
|
||||
p.read()
|
||||
switch p.chr {
|
||||
case 'x', 'X':
|
||||
// Hexadecimal
|
||||
self.read()
|
||||
if isDigit(self.chr, 16) {
|
||||
self.read()
|
||||
p.read()
|
||||
if isDigit(p.chr, 16) {
|
||||
p.read()
|
||||
} 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"
|
||||
self.error(0, "Illegal hexadecimal number")
|
||||
p.error(0, "Illegal hexadecimal number")
|
||||
}
|
||||
|
||||
goto hexadecimal
|
||||
} else if self.chr == '.' {
|
||||
case '.':
|
||||
// Float
|
||||
goto float
|
||||
} else {
|
||||
default:
|
||||
// Octal, Float
|
||||
if self.chr == 'e' || self.chr == 'E' {
|
||||
if p.chr == 'e' || p.chr == 'E' {
|
||||
goto exponent
|
||||
}
|
||||
self.scanMantissa(8)
|
||||
if self.chr == '8' || self.chr == '9' {
|
||||
return token.ILLEGAL, self.str[offset:self.chrOffset]
|
||||
p.scanMantissa(8)
|
||||
if p.chr == '8' || p.chr == '9' {
|
||||
return token.ILLEGAL, p.str[offset:p.chrOffset]
|
||||
}
|
||||
goto octal
|
||||
}
|
||||
}
|
||||
|
||||
self.scanMantissa(10)
|
||||
p.scanMantissa(10)
|
||||
|
||||
float:
|
||||
if self.chr == '.' {
|
||||
self.read()
|
||||
self.scanMantissa(10)
|
||||
if p.chr == '.' {
|
||||
p.read()
|
||||
p.scanMantissa(10)
|
||||
}
|
||||
|
||||
exponent:
|
||||
if self.chr == 'e' || self.chr == 'E' {
|
||||
self.read()
|
||||
if self.chr == '-' || self.chr == '+' {
|
||||
self.read()
|
||||
if p.chr == 'e' || p.chr == 'E' {
|
||||
p.read()
|
||||
if p.chr == '-' || p.chr == '+' {
|
||||
p.read()
|
||||
}
|
||||
if isDecimalDigit(self.chr) {
|
||||
self.read()
|
||||
self.scanMantissa(10)
|
||||
if isDecimalDigit(p.chr) {
|
||||
p.read()
|
||||
p.scanMantissa(10)
|
||||
} else {
|
||||
return token.ILLEGAL, self.str[offset:self.chrOffset]
|
||||
return token.ILLEGAL, p.str[offset:p.chrOffset]
|
||||
}
|
||||
}
|
||||
|
||||
hexadecimal:
|
||||
octal:
|
||||
if isIdentifierStart(self.chr) || isDecimalDigit(self.chr) {
|
||||
return token.ILLEGAL, self.str[offset:self.chrOffset]
|
||||
if isIdentifierStart(p.chr) || isDecimalDigit(p.chr) {
|
||||
return token.ILLEGAL, p.str[offset:p.chrOffset]
|
||||
}
|
||||
|
||||
return tkn, self.str[offset:self.chrOffset]
|
||||
return tkn, p.str[offset:p.chrOffset]
|
||||
}
|
||||
|
|
134
v1/vendor/github.com/robertkrimen/otto/parser/parser.go
generated
vendored
|
@ -35,9 +35,9 @@ package parser
|
|||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
"github.com/robertkrimen/otto/ast"
|
||||
"github.com/robertkrimen/otto/file"
|
||||
|
@ -49,11 +49,14 @@ import (
|
|||
type Mode uint
|
||||
|
||||
const (
|
||||
IgnoreRegExpErrors Mode = 1 << iota // Ignore RegExp compatibility errors (allow backtracking)
|
||||
StoreComments // Store the comments from source to the comments map
|
||||
// IgnoreRegExpErrors ignores RegExp compatibility errors (allow backtracking).
|
||||
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
|
||||
length int
|
||||
base int
|
||||
|
@ -66,7 +69,7 @@ type _parser struct {
|
|||
token token.Token // The token
|
||||
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
|
||||
implicitSemicolon bool // An implicit semicolon exists
|
||||
|
||||
|
@ -85,12 +88,13 @@ type _parser struct {
|
|||
comments *ast.Comments
|
||||
}
|
||||
|
||||
// Parser is implemented by types which can parse JavaScript Code.
|
||||
type Parser interface {
|
||||
Scan() (tkn token.Token, literal string, idx file.Idx)
|
||||
}
|
||||
|
||||
func _newParser(filename, src string, base int, sm *sourcemap.Consumer) *_parser {
|
||||
return &_parser{
|
||||
func newParser(filename, src string, base int, sm *sourcemap.Consumer) *parser {
|
||||
return &parser{
|
||||
chr: ' ', // This is set so we can start scanning by skipping whitespace
|
||||
str: 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 {
|
||||
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) {
|
||||
if src != nil {
|
||||
switch src := src.(type) {
|
||||
|
@ -122,12 +127,14 @@ func ReadSource(filename string, src interface{}) ([]byte, error) {
|
|||
return nil, err
|
||||
}
|
||||
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) {
|
||||
if src == nil {
|
||||
return nil, nil //nolint: nilnil
|
||||
|
@ -139,9 +146,7 @@ func ReadSourceMap(filename string, src interface{}) (*sourcemap.Consumer, error
|
|||
case []byte:
|
||||
return sourcemap.Parse(filename, src)
|
||||
case *bytes.Buffer:
|
||||
if src != nil {
|
||||
return sourcemap.Parse(filename, src.Bytes())
|
||||
}
|
||||
case io.Reader:
|
||||
var bfr bytes.Buffer
|
||||
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())
|
||||
case *sourcemap.Consumer:
|
||||
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) {
|
||||
src, err := ReadSource(filename, javascriptSource)
|
||||
if err != nil {
|
||||
|
@ -184,10 +190,10 @@ func ParseFileWithSourceMap(fileSet *file.FileSet, filename string, javascriptSo
|
|||
base = fileSet.AddFile(filename, string(src))
|
||||
}
|
||||
|
||||
parser := _newParser(filename, string(src), base, sm)
|
||||
parser.mode = mode
|
||||
program, err := parser.parse()
|
||||
program.Comments = parser.comments.CommentMap
|
||||
p := newParser(filename, string(src), base, sm)
|
||||
p.mode = mode
|
||||
program, err := p.parse()
|
||||
program.Comments = p.comments.CommentMap
|
||||
|
||||
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) {
|
||||
src := "(function(" + parameterList + ") {\n" + body + "\n})"
|
||||
|
||||
parser := _newParser("", src, 1, nil)
|
||||
program, err := parser.parse()
|
||||
p := newParser("", src, 1, nil)
|
||||
program, err := p.parse()
|
||||
if err != nil {
|
||||
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
|
||||
// returns the token.Token token, a string literal representing the value of the token (if applicable)
|
||||
// and it's current file.Idx index.
|
||||
func (self *_parser) Scan() (tkn token.Token, literal string, idx file.Idx) {
|
||||
return self.scan()
|
||||
func (p *parser) Scan() (token.Token, string, file.Idx) {
|
||||
return p.scan()
|
||||
}
|
||||
|
||||
func (self *_parser) slice(idx0, idx1 file.Idx) string {
|
||||
from := int(idx0) - self.base
|
||||
to := int(idx1) - self.base
|
||||
if from >= 0 && to <= len(self.str) {
|
||||
return self.str[from:to]
|
||||
func (p *parser) slice(idx0, idx1 file.Idx) string {
|
||||
from := int(idx0) - p.base
|
||||
to := int(idx1) - p.base
|
||||
if from >= 0 && to <= len(p.str) {
|
||||
return p.str[from:to]
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *_parser) parse() (*ast.Program, error) {
|
||||
self.next()
|
||||
program := self.parseProgram()
|
||||
func (p *parser) parse() (*ast.Program, error) {
|
||||
p.next()
|
||||
program := p.parseProgram()
|
||||
if false {
|
||||
self.errors.Sort()
|
||||
p.errors.Sort()
|
||||
}
|
||||
|
||||
if self.mode&StoreComments != 0 {
|
||||
self.comments.CommentMap.AddComments(program, self.comments.FetchAll(), ast.TRAILING)
|
||||
if p.mode&StoreComments != 0 {
|
||||
p.comments.CommentMap.AddComments(program, p.comments.FetchAll(), ast.TRAILING)
|
||||
}
|
||||
|
||||
return program, self.errors.Err()
|
||||
return program, p.errors.Err()
|
||||
}
|
||||
|
||||
func (self *_parser) next() {
|
||||
self.token, self.literal, self.idx = self.scan()
|
||||
func (p *parser) next() {
|
||||
p.token, p.literal, p.idx = p.scan()
|
||||
}
|
||||
|
||||
func (self *_parser) optionalSemicolon() {
|
||||
if self.token == token.SEMICOLON {
|
||||
self.next()
|
||||
func (p *parser) optionalSemicolon() {
|
||||
if p.token == token.SEMICOLON {
|
||||
p.next()
|
||||
return
|
||||
}
|
||||
|
||||
if self.implicitSemicolon {
|
||||
self.implicitSemicolon = false
|
||||
if p.implicitSemicolon {
|
||||
p.implicitSemicolon = false
|
||||
return
|
||||
}
|
||||
|
||||
if self.token != token.EOF && self.token != token.RIGHT_BRACE {
|
||||
self.expect(token.SEMICOLON)
|
||||
if p.token != token.EOF && p.token != token.RIGHT_BRACE {
|
||||
p.expect(token.SEMICOLON)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *_parser) semicolon() {
|
||||
if self.token != token.RIGHT_PARENTHESIS && self.token != token.RIGHT_BRACE {
|
||||
if self.implicitSemicolon {
|
||||
self.implicitSemicolon = false
|
||||
func (p *parser) semicolon() {
|
||||
if p.token != token.RIGHT_PARENTHESIS && p.token != token.RIGHT_BRACE {
|
||||
if p.implicitSemicolon {
|
||||
p.implicitSemicolon = false
|
||||
return
|
||||
}
|
||||
|
||||
self.expect(token.SEMICOLON)
|
||||
p.expect(token.SEMICOLON)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *_parser) idxOf(offset int) file.Idx {
|
||||
return file.Idx(self.base + offset)
|
||||
func (p *parser) idxOf(offset int) file.Idx {
|
||||
return file.Idx(p.base + offset)
|
||||
}
|
||||
|
||||
func (self *_parser) expect(value token.Token) file.Idx {
|
||||
idx := self.idx
|
||||
if self.token != value {
|
||||
self.errorUnexpectedToken(self.token)
|
||||
func (p *parser) expect(value token.Token) file.Idx {
|
||||
idx := p.idx
|
||||
if p.token != value {
|
||||
p.errorUnexpectedToken(p.token)
|
||||
}
|
||||
self.next()
|
||||
p.next()
|
||||
return idx
|
||||
}
|
||||
|
||||
|
@ -305,17 +311,17 @@ func lineCount(str string) (int, int) {
|
|||
for index, chr := range str {
|
||||
switch chr {
|
||||
case '\r':
|
||||
line += 1
|
||||
line++
|
||||
last = index
|
||||
pair = true
|
||||
continue
|
||||
case '\n':
|
||||
if !pair {
|
||||
line += 1
|
||||
line++
|
||||
}
|
||||
last = index
|
||||
case '\u2028', '\u2029':
|
||||
line += 1
|
||||
line++
|
||||
last = index + 2
|
||||
}
|
||||
pair = false
|
||||
|
@ -323,11 +329,11 @@ func lineCount(str string) (int, int) {
|
|||
return line, last
|
||||
}
|
||||
|
||||
func (self *_parser) position(idx file.Idx) file.Position {
|
||||
func (p *parser) position(idx file.Idx) file.Position {
|
||||
position := file.Position{}
|
||||
offset := int(idx) - self.base
|
||||
str := self.str[:offset]
|
||||
position.Filename = self.file.Name()
|
||||
offset := int(idx) - p.base
|
||||
str := p.str[:offset]
|
||||
position.Filename = p.file.Name()
|
||||
line, last := lineCount(str)
|
||||
position.Line = 1 + line
|
||||
if last >= 0 {
|
||||
|
|
250
v1/vendor/github.com/robertkrimen/otto/parser/regexp.go
generated
vendored
|
@ -6,7 +6,7 @@ import (
|
|||
"strconv"
|
||||
)
|
||||
|
||||
type _RegExp_parser struct {
|
||||
type regExpParser struct { //nolint: maligned
|
||||
str string
|
||||
length int
|
||||
|
||||
|
@ -40,128 +40,128 @@ func TransformRegExp(pattern string) (string, error) {
|
|||
|
||||
// TODO If without \, if without (?=, (?!, then another shortcut
|
||||
|
||||
parser := _RegExp_parser{
|
||||
p := regExpParser{
|
||||
str: pattern,
|
||||
length: len(pattern),
|
||||
goRegexp: bytes.NewBuffer(make([]byte, 0, 3*len(pattern)/2)),
|
||||
}
|
||||
parser.read() // Pull in the first character
|
||||
parser.scan()
|
||||
p.read() // Pull in the first character
|
||||
p.scan()
|
||||
var err error
|
||||
if len(parser.errors) > 0 {
|
||||
err = parser.errors[0]
|
||||
if len(p.errors) > 0 {
|
||||
err = p.errors[0]
|
||||
}
|
||||
if parser.invalid {
|
||||
if p.invalid {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// 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() {
|
||||
for self.chr != -1 {
|
||||
switch self.chr {
|
||||
func (p *regExpParser) scan() {
|
||||
for p.chr != -1 {
|
||||
switch p.chr {
|
||||
case '\\':
|
||||
self.read()
|
||||
self.scanEscape(false)
|
||||
p.read()
|
||||
p.scanEscape(false)
|
||||
case '(':
|
||||
self.pass()
|
||||
self.scanGroup()
|
||||
p.pass()
|
||||
p.scanGroup()
|
||||
case '[':
|
||||
self.pass()
|
||||
self.scanBracket()
|
||||
p.pass()
|
||||
p.scanBracket()
|
||||
case ')':
|
||||
self.error(-1, "Unmatched ')'")
|
||||
self.invalid = true
|
||||
self.pass()
|
||||
p.error(-1, "Unmatched ')'")
|
||||
p.invalid = true
|
||||
p.pass()
|
||||
default:
|
||||
self.pass()
|
||||
p.pass()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// (...)
|
||||
func (self *_RegExp_parser) scanGroup() {
|
||||
str := self.str[self.chrOffset:]
|
||||
func (p *regExpParser) scanGroup() {
|
||||
str := p.str[p.chrOffset:]
|
||||
if len(str) > 1 { // A possibility of (?= or (?!
|
||||
if str[0] == '?' {
|
||||
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 != ')' {
|
||||
switch self.chr {
|
||||
for p.chr != -1 && p.chr != ')' {
|
||||
switch p.chr {
|
||||
case '\\':
|
||||
self.read()
|
||||
self.scanEscape(false)
|
||||
p.read()
|
||||
p.scanEscape(false)
|
||||
case '(':
|
||||
self.pass()
|
||||
self.scanGroup()
|
||||
p.pass()
|
||||
p.scanGroup()
|
||||
case '[':
|
||||
self.pass()
|
||||
self.scanBracket()
|
||||
p.pass()
|
||||
p.scanBracket()
|
||||
default:
|
||||
self.pass()
|
||||
p.pass()
|
||||
continue
|
||||
}
|
||||
}
|
||||
if self.chr != ')' {
|
||||
self.error(-1, "Unterminated group")
|
||||
self.invalid = true
|
||||
if p.chr != ')' {
|
||||
p.error(-1, "Unterminated group")
|
||||
p.invalid = true
|
||||
return
|
||||
}
|
||||
self.pass()
|
||||
p.pass()
|
||||
}
|
||||
|
||||
// [...]
|
||||
func (self *_RegExp_parser) scanBracket() {
|
||||
for self.chr != -1 {
|
||||
if self.chr == ']' {
|
||||
// [...].
|
||||
func (p *regExpParser) scanBracket() {
|
||||
for p.chr != -1 {
|
||||
if p.chr == ']' {
|
||||
break
|
||||
} else if self.chr == '\\' {
|
||||
self.read()
|
||||
self.scanEscape(true)
|
||||
} else if p.chr == '\\' {
|
||||
p.read()
|
||||
p.scanEscape(true)
|
||||
continue
|
||||
}
|
||||
self.pass()
|
||||
p.pass()
|
||||
}
|
||||
if self.chr != ']' {
|
||||
self.error(-1, "Unterminated character class")
|
||||
self.invalid = true
|
||||
if p.chr != ']' {
|
||||
p.error(-1, "Unterminated character class")
|
||||
p.invalid = true
|
||||
return
|
||||
}
|
||||
self.pass()
|
||||
p.pass()
|
||||
}
|
||||
|
||||
// \...
|
||||
func (self *_RegExp_parser) scanEscape(inClass bool) {
|
||||
offset := self.chrOffset
|
||||
func (p *regExpParser) scanEscape(inClass bool) {
|
||||
offset := p.chrOffset
|
||||
|
||||
var length, base uint32
|
||||
switch self.chr {
|
||||
switch p.chr {
|
||||
case '0', '1', '2', '3', '4', '5', '6', '7':
|
||||
var value int64
|
||||
size := 0
|
||||
for {
|
||||
digit := int64(digitValue(self.chr))
|
||||
digit := int64(digitValue(p.chr))
|
||||
if digit >= 8 {
|
||||
// Not a valid digit
|
||||
break
|
||||
}
|
||||
value = value*8 + digit
|
||||
self.read()
|
||||
size += 1
|
||||
p.read()
|
||||
size++
|
||||
}
|
||||
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 {
|
||||
self.errors = append(self.errors, err)
|
||||
p.errors = append(p.errors, err)
|
||||
}
|
||||
if value != 0 {
|
||||
// An invalid backreference
|
||||
self.error(-1, "re2: Invalid \\%d <backreference>", value)
|
||||
p.error(-1, "re2: Invalid \\%d <backreference>", value)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
@ -172,49 +172,49 @@ func (self *_RegExp_parser) scanEscape(inClass bool) {
|
|||
tmp = tmp[0:3]
|
||||
}
|
||||
tmp = strconv.AppendInt(tmp, value, 16)
|
||||
_, err := self.goRegexp.Write(tmp)
|
||||
_, err := p.goRegexp.Write(tmp)
|
||||
if err != nil {
|
||||
self.errors = append(self.errors, err)
|
||||
p.errors = append(p.errors, err)
|
||||
}
|
||||
return
|
||||
|
||||
case '8', '9':
|
||||
size := 0
|
||||
for {
|
||||
digit := digitValue(self.chr)
|
||||
digit := digitValue(p.chr)
|
||||
if digit >= 10 {
|
||||
// Not a valid digit
|
||||
break
|
||||
}
|
||||
self.read()
|
||||
size += 1
|
||||
p.read()
|
||||
size++
|
||||
}
|
||||
err := self.goRegexp.WriteByte('\\')
|
||||
err := p.goRegexp.WriteByte('\\')
|
||||
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 {
|
||||
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
|
||||
|
||||
case 'x':
|
||||
self.read()
|
||||
p.read()
|
||||
length, base = 2, 16
|
||||
|
||||
case 'u':
|
||||
self.read()
|
||||
p.read()
|
||||
length, base = 4, 16
|
||||
|
||||
case 'b':
|
||||
if inClass {
|
||||
_, err := self.goRegexp.Write([]byte{'\\', 'x', '0', '8'})
|
||||
_, err := p.goRegexp.Write([]byte{'\\', 'x', '0', '8'})
|
||||
if err != nil {
|
||||
self.errors = append(self.errors, err)
|
||||
p.errors = append(p.errors, err)
|
||||
}
|
||||
self.read()
|
||||
p.read()
|
||||
return
|
||||
}
|
||||
fallthrough
|
||||
|
@ -231,24 +231,25 @@ func (self *_RegExp_parser) scanEscape(inClass bool) {
|
|||
fallthrough
|
||||
|
||||
case 'f', 'n', 'r', 't', 'v':
|
||||
err := self.goRegexp.WriteByte('\\')
|
||||
err := p.goRegexp.WriteByte('\\')
|
||||
if err != nil {
|
||||
self.errors = append(self.errors, err)
|
||||
p.errors = append(p.errors, err)
|
||||
}
|
||||
self.pass()
|
||||
p.pass()
|
||||
return
|
||||
|
||||
case 'c':
|
||||
self.read()
|
||||
p.read()
|
||||
var value int64
|
||||
if 'a' <= self.chr && self.chr <= 'z' {
|
||||
value = int64(self.chr) - 'a' + 1
|
||||
} else if 'A' <= self.chr && self.chr <= 'Z' {
|
||||
value = int64(self.chr) - 'A' + 1
|
||||
} else {
|
||||
err := self.goRegexp.WriteByte('c')
|
||||
switch {
|
||||
case 'a' <= p.chr && p.chr <= 'z':
|
||||
value = int64(p.chr) - 'a' + 1
|
||||
case 'A' <= p.chr && p.chr <= 'Z':
|
||||
value = int64(p.chr) - 'A' + 1
|
||||
default:
|
||||
err := p.goRegexp.WriteByte('c')
|
||||
if err != nil {
|
||||
self.errors = append(self.errors, err)
|
||||
p.errors = append(p.errors, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
@ -259,98 +260,93 @@ func (self *_RegExp_parser) scanEscape(inClass bool) {
|
|||
tmp = tmp[0:3]
|
||||
}
|
||||
tmp = strconv.AppendInt(tmp, value, 16)
|
||||
_, err := self.goRegexp.Write(tmp)
|
||||
_, err := p.goRegexp.Write(tmp)
|
||||
if err != nil {
|
||||
self.errors = append(self.errors, err)
|
||||
p.errors = append(p.errors, err)
|
||||
}
|
||||
self.read()
|
||||
p.read()
|
||||
return
|
||||
|
||||
default:
|
||||
// $ is an identifier character, so we have to have
|
||||
// a special case for it here
|
||||
if self.chr == '$' || !isIdentifierPart(self.chr) {
|
||||
if p.chr == '$' || !isIdentifierPart(p.chr) {
|
||||
// A non-identifier character needs escaping
|
||||
err := self.goRegexp.WriteByte('\\')
|
||||
err := p.goRegexp.WriteByte('\\')
|
||||
if err != nil {
|
||||
self.errors = append(self.errors, err)
|
||||
p.errors = append(p.errors, err)
|
||||
}
|
||||
} else {
|
||||
} else { //nolint: staticcheck
|
||||
// Unescape the character for re2
|
||||
}
|
||||
self.pass()
|
||||
p.pass()
|
||||
return
|
||||
}
|
||||
|
||||
// Otherwise, we're a \u.... or \x...
|
||||
valueOffset := self.chrOffset
|
||||
valueOffset := p.chrOffset
|
||||
|
||||
var value uint32
|
||||
{
|
||||
length := length
|
||||
for ; length > 0; length-- {
|
||||
digit := uint32(digitValue(self.chr))
|
||||
for length := length; length > 0; length-- {
|
||||
digit := uint32(digitValue(p.chr))
|
||||
if digit >= base {
|
||||
// Not a valid digit
|
||||
goto skip
|
||||
}
|
||||
value = value*base + digit
|
||||
self.read()
|
||||
}
|
||||
p.read()
|
||||
}
|
||||
|
||||
if length == 4 {
|
||||
_, err := self.goRegexp.Write([]byte{
|
||||
switch length {
|
||||
case 4:
|
||||
if _, err := p.goRegexp.Write([]byte{
|
||||
'\\',
|
||||
'x',
|
||||
'{',
|
||||
self.str[valueOffset+0],
|
||||
self.str[valueOffset+1],
|
||||
self.str[valueOffset+2],
|
||||
self.str[valueOffset+3],
|
||||
p.str[valueOffset+0],
|
||||
p.str[valueOffset+1],
|
||||
p.str[valueOffset+2],
|
||||
p.str[valueOffset+3],
|
||||
'}',
|
||||
})
|
||||
if err != nil {
|
||||
self.errors = append(self.errors, err)
|
||||
}); err != nil {
|
||||
p.errors = append(p.errors, err)
|
||||
}
|
||||
} else if length == 2 {
|
||||
_, err := self.goRegexp.Write([]byte{
|
||||
case 2:
|
||||
if _, err := p.goRegexp.Write([]byte{
|
||||
'\\',
|
||||
'x',
|
||||
self.str[valueOffset+0],
|
||||
self.str[valueOffset+1],
|
||||
})
|
||||
if err != nil {
|
||||
self.errors = append(self.errors, err)
|
||||
p.str[valueOffset+0],
|
||||
p.str[valueOffset+1],
|
||||
}); err != nil {
|
||||
p.errors = append(p.errors, err)
|
||||
}
|
||||
} else {
|
||||
default:
|
||||
// Should never, ever get here...
|
||||
self.error(-1, "re2: Illegal branch in scanEscape")
|
||||
p.error(-1, "re2: Illegal branch in scanEscape")
|
||||
goto skip
|
||||
}
|
||||
|
||||
return
|
||||
|
||||
skip:
|
||||
_, err := self.goRegexp.WriteString(self.str[offset:self.chrOffset])
|
||||
_, err := p.goRegexp.WriteString(p.str[offset:p.chrOffset])
|
||||
if err != nil {
|
||||
self.errors = append(self.errors, err)
|
||||
p.errors = append(p.errors, err)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *_RegExp_parser) pass() {
|
||||
if self.chr != -1 {
|
||||
_, err := self.goRegexp.WriteRune(self.chr)
|
||||
func (p *regExpParser) pass() {
|
||||
if p.chr != -1 {
|
||||
_, err := p.goRegexp.WriteRune(p.chr)
|
||||
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.
|
||||
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...)
|
||||
self.errors = append(self.errors, err)
|
||||
return err
|
||||
p.errors = append(p.errors, err)
|
||||
}
|
||||
|
|
26
v1/vendor/github.com/robertkrimen/otto/parser/scope.go
generated
vendored
|
@ -4,8 +4,8 @@ import (
|
|||
"github.com/robertkrimen/otto/ast"
|
||||
)
|
||||
|
||||
type _scope struct {
|
||||
outer *_scope
|
||||
type scope struct {
|
||||
outer *scope
|
||||
allowIn bool
|
||||
inIteration bool
|
||||
inSwitch bool
|
||||
|
@ -15,30 +15,30 @@ type _scope struct {
|
|||
labels []string
|
||||
}
|
||||
|
||||
func (self *_parser) openScope() {
|
||||
self.scope = &_scope{
|
||||
outer: self.scope,
|
||||
func (p *parser) openScope() {
|
||||
p.scope = &scope{
|
||||
outer: p.scope,
|
||||
allowIn: true,
|
||||
}
|
||||
}
|
||||
|
||||
func (self *_parser) closeScope() {
|
||||
self.scope = self.scope.outer
|
||||
func (p *parser) closeScope() {
|
||||
p.scope = p.scope.outer
|
||||
}
|
||||
|
||||
func (self *_scope) declare(declaration ast.Declaration) {
|
||||
self.declarationList = append(self.declarationList, declaration)
|
||||
func (p *scope) declare(declaration ast.Declaration) {
|
||||
p.declarationList = append(p.declarationList, declaration)
|
||||
}
|
||||
|
||||
func (self *_scope) hasLabel(name string) bool {
|
||||
for _, label := range self.labels {
|
||||
func (p *scope) hasLabel(name string) bool {
|
||||
for _, label := range p.labels {
|
||||
if label == name {
|
||||
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
|
||||
return self.outer.hasLabel(name)
|
||||
return p.outer.hasLabel(name)
|
||||
}
|
||||
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
|
||||
|
||||
type _propertyMode int
|
||||
type propertyMode int
|
||||
|
||||
const (
|
||||
modeWriteMask _propertyMode = 0700
|
||||
modeEnumerateMask = 0070
|
||||
modeConfigureMask = 0007
|
||||
modeOnMask = 0111
|
||||
modeSetMask = 0222 // If value is 2, then mode is neither "On" nor "Off"
|
||||
modeWriteMask propertyMode = 0o700
|
||||
modeEnumerateMask propertyMode = 0o070
|
||||
modeConfigureMask propertyMode = 0o007
|
||||
modeOnMask propertyMode = 0o111
|
||||
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{}
|
||||
mode _propertyMode
|
||||
mode propertyMode
|
||||
}
|
||||
|
||||
func (self _property) writable() bool {
|
||||
return self.mode&modeWriteMask == modeWriteMask&modeOnMask
|
||||
func (p property) writable() bool {
|
||||
return p.mode&modeWriteMask == modeWriteMask&modeOnMask
|
||||
}
|
||||
|
||||
func (self *_property) writeOn() {
|
||||
self.mode = (self.mode & ^modeWriteMask) | (modeWriteMask & modeOnMask)
|
||||
func (p *property) writeOn() {
|
||||
p.mode = (p.mode & ^modeWriteMask) | (modeWriteMask & modeOnMask)
|
||||
}
|
||||
|
||||
func (self *_property) writeOff() {
|
||||
self.mode &= ^modeWriteMask
|
||||
func (p *property) writeOff() {
|
||||
p.mode &= ^modeWriteMask
|
||||
}
|
||||
|
||||
func (self *_property) writeClear() {
|
||||
self.mode = (self.mode & ^modeWriteMask) | (modeWriteMask & modeSetMask)
|
||||
func (p *property) writeClear() {
|
||||
p.mode = (p.mode & ^modeWriteMask) | (modeWriteMask & modeSetMask)
|
||||
}
|
||||
|
||||
func (self _property) writeSet() bool {
|
||||
return 0 == self.mode&modeWriteMask&modeSetMask
|
||||
func (p property) writeSet() bool {
|
||||
return p.mode&modeWriteMask&modeSetMask == 0
|
||||
}
|
||||
|
||||
func (self _property) enumerable() bool {
|
||||
return self.mode&modeEnumerateMask == modeEnumerateMask&modeOnMask
|
||||
func (p property) enumerable() bool {
|
||||
return p.mode&modeEnumerateMask == modeEnumerateMask&modeOnMask
|
||||
}
|
||||
|
||||
func (self *_property) enumerateOn() {
|
||||
self.mode = (self.mode & ^modeEnumerateMask) | (modeEnumerateMask & modeOnMask)
|
||||
func (p *property) enumerateOn() {
|
||||
p.mode = (p.mode & ^modeEnumerateMask) | (modeEnumerateMask & modeOnMask)
|
||||
}
|
||||
|
||||
func (self *_property) enumerateOff() {
|
||||
self.mode &= ^modeEnumerateMask
|
||||
func (p *property) enumerateOff() {
|
||||
p.mode &= ^modeEnumerateMask
|
||||
}
|
||||
|
||||
func (self _property) enumerateSet() bool {
|
||||
return 0 == self.mode&modeEnumerateMask&modeSetMask
|
||||
func (p property) enumerateSet() bool {
|
||||
return p.mode&modeEnumerateMask&modeSetMask == 0
|
||||
}
|
||||
|
||||
func (self _property) configurable() bool {
|
||||
return self.mode&modeConfigureMask == modeConfigureMask&modeOnMask
|
||||
func (p property) configurable() bool {
|
||||
return p.mode&modeConfigureMask == modeConfigureMask&modeOnMask
|
||||
}
|
||||
|
||||
func (self *_property) configureOn() {
|
||||
self.mode = (self.mode & ^modeConfigureMask) | (modeConfigureMask & modeOnMask)
|
||||
func (p *property) configureOn() {
|
||||
p.mode = (p.mode & ^modeConfigureMask) | (modeConfigureMask & modeOnMask)
|
||||
}
|
||||
|
||||
func (self *_property) configureOff() {
|
||||
self.mode &= ^modeConfigureMask
|
||||
func (p *property) configureOff() {
|
||||
p.mode &= ^modeConfigureMask
|
||||
}
|
||||
|
||||
func (self _property) configureSet() bool {
|
||||
return 0 == self.mode&modeConfigureMask&modeSetMask
|
||||
func (p property) configureSet() bool { //nolint: unused
|
||||
return p.mode&modeConfigureMask&modeSetMask == 0
|
||||
}
|
||||
|
||||
func (self _property) copy() *_property {
|
||||
property := self
|
||||
return &property
|
||||
func (p property) copy() *property { //nolint: unused
|
||||
cpy := p
|
||||
return &cpy
|
||||
}
|
||||
|
||||
func (self _property) get(this *_object) Value {
|
||||
switch value := self.value.(type) {
|
||||
func (p property) get(this *object) Value {
|
||||
switch value := p.value.(type) {
|
||||
case Value:
|
||||
return value
|
||||
case _propertyGetSet:
|
||||
case propertyGetSet:
|
||||
if value[0] != nil {
|
||||
return value[0].call(toValue(this), nil, false, nativeFrame)
|
||||
}
|
||||
|
@ -90,37 +90,37 @@ func (self _property) get(this *_object) Value {
|
|||
return Value{}
|
||||
}
|
||||
|
||||
func (self _property) isAccessorDescriptor() bool {
|
||||
setGet, test := self.value.(_propertyGetSet)
|
||||
func (p property) isAccessorDescriptor() bool {
|
||||
setGet, test := p.value.(propertyGetSet)
|
||||
return test && (setGet[0] != nil || setGet[1] != nil)
|
||||
}
|
||||
|
||||
func (self _property) isDataDescriptor() bool {
|
||||
if self.writeSet() { // Either "On" or "Off"
|
||||
func (p property) isDataDescriptor() bool {
|
||||
if p.writeSet() { // Either "On" or "Off"
|
||||
return true
|
||||
}
|
||||
value, valid := self.value.(Value)
|
||||
value, valid := p.value.(Value)
|
||||
return valid && !value.isEmpty()
|
||||
}
|
||||
|
||||
func (self _property) isGenericDescriptor() bool {
|
||||
return !(self.isDataDescriptor() || self.isAccessorDescriptor())
|
||||
func (p property) isGenericDescriptor() bool {
|
||||
return !(p.isDataDescriptor() || p.isAccessorDescriptor())
|
||||
}
|
||||
|
||||
func (self _property) isEmpty() bool {
|
||||
return self.mode == 0222 && self.isGenericDescriptor()
|
||||
func (p property) isEmpty() bool {
|
||||
return p.mode == 0o222 && p.isGenericDescriptor()
|
||||
}
|
||||
|
||||
// _enumerableValue, _enumerableTrue, _enumerableFalse?
|
||||
// .enumerableValue() .enumerableExists()
|
||||
|
||||
func toPropertyDescriptor(rt *_runtime, value Value) (descriptor _property) {
|
||||
objectDescriptor := value._object()
|
||||
func toPropertyDescriptor(rt *runtime, value Value) property {
|
||||
objectDescriptor := value.object()
|
||||
if objectDescriptor == nil {
|
||||
panic(rt.panicTypeError())
|
||||
panic(rt.panicTypeError("toPropertyDescriptor on nil"))
|
||||
}
|
||||
|
||||
{
|
||||
var descriptor property
|
||||
descriptor.mode = modeSetMask // Initially nothing is set
|
||||
if objectDescriptor.hasProperty("enumerable") {
|
||||
if objectDescriptor.get("enumerable").bool() {
|
||||
|
@ -145,21 +145,20 @@ func toPropertyDescriptor(rt *_runtime, value Value) (descriptor _property) {
|
|||
descriptor.writeOff()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var getter, setter *_object
|
||||
var getter, setter *object
|
||||
getterSetter := false
|
||||
|
||||
if objectDescriptor.hasProperty("get") {
|
||||
value := objectDescriptor.get("get")
|
||||
if value.IsDefined() {
|
||||
if !value.isCallable() {
|
||||
panic(rt.panicTypeError())
|
||||
panic(rt.panicTypeError("toPropertyDescriptor get not callable"))
|
||||
}
|
||||
getter = value._object()
|
||||
getter = value.object()
|
||||
getterSetter = true
|
||||
} else {
|
||||
getter = &_nilGetSetObject
|
||||
getter = &nilGetSetObject
|
||||
getterSetter = true
|
||||
}
|
||||
}
|
||||
|
@ -168,52 +167,52 @@ func toPropertyDescriptor(rt *_runtime, value Value) (descriptor _property) {
|
|||
value := objectDescriptor.get("set")
|
||||
if value.IsDefined() {
|
||||
if !value.isCallable() {
|
||||
panic(rt.panicTypeError())
|
||||
panic(rt.panicTypeError("toPropertyDescriptor set not callable"))
|
||||
}
|
||||
setter = value._object()
|
||||
setter = value.object()
|
||||
getterSetter = true
|
||||
} else {
|
||||
setter = &_nilGetSetObject
|
||||
setter = &nilGetSetObject
|
||||
getterSetter = true
|
||||
}
|
||||
}
|
||||
|
||||
if getterSetter {
|
||||
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 getterSetter {
|
||||
panic(rt.panicTypeError())
|
||||
panic(rt.panicTypeError("toPropertyDescriptor value getterSetter"))
|
||||
}
|
||||
descriptor.value = objectDescriptor.get("value")
|
||||
}
|
||||
|
||||
return
|
||||
return descriptor
|
||||
}
|
||||
|
||||
func (self *_runtime) fromPropertyDescriptor(descriptor _property) *_object {
|
||||
object := self.newObject()
|
||||
func (rt *runtime) fromPropertyDescriptor(descriptor property) *object {
|
||||
obj := rt.newObject()
|
||||
if descriptor.isDataDescriptor() {
|
||||
object.defineProperty("value", descriptor.value.(Value), 0111, false)
|
||||
object.defineProperty("writable", toValue_bool(descriptor.writable()), 0111, false)
|
||||
obj.defineProperty("value", descriptor.value.(Value), 0o111, false)
|
||||
obj.defineProperty("writable", boolValue(descriptor.writable()), 0o111, false)
|
||||
} else if descriptor.isAccessorDescriptor() {
|
||||
getSet := descriptor.value.(_propertyGetSet)
|
||||
getSet := descriptor.value.(propertyGetSet)
|
||||
get := Value{}
|
||||
if getSet[0] != nil {
|
||||
get = toValue_object(getSet[0])
|
||||
get = objectValue(getSet[0])
|
||||
}
|
||||
set := Value{}
|
||||
if getSet[1] != nil {
|
||||
set = toValue_object(getSet[1])
|
||||
set = objectValue(getSet[1])
|
||||
}
|
||||
object.defineProperty("get", get, 0111, false)
|
||||
object.defineProperty("set", set, 0111, false)
|
||||
obj.defineProperty("get", get, 0o111, false)
|
||||
obj.defineProperty("set", set, 0o111, false)
|
||||
}
|
||||
object.defineProperty("enumerable", toValue_bool(descriptor.enumerable()), 0111, false)
|
||||
object.defineProperty("configurable", toValue_bool(descriptor.configurable()), 0111, false)
|
||||
return object
|
||||
obj.defineProperty("enumerable", boolValue(descriptor.enumerable()), 0o111, false)
|
||||
obj.defineProperty("configurable", boolValue(descriptor.configurable()), 0o111, false)
|
||||
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 expirmental package to facillitate altering the otto runtime via import.
|
||||
|
||||
This interface can change at any time.
|
||||
*/
|
||||
// Package registry is an experimental package to facilitate altering the otto runtime via import.
|
||||
//
|
||||
// This interface can change at any time.
|
||||
package registry
|
||||
|
||||
var registry []*Entry = make([]*Entry, 0)
|
||||
|
||||
// Entry represents a registry entry.
|
||||
type Entry struct {
|
||||
active bool
|
||||
source func() string
|
||||
}
|
||||
|
||||
// newEntry returns a new Entry for source.
|
||||
func newEntry(source func() string) *Entry {
|
||||
return &Entry{
|
||||
active: true,
|
||||
|
@ -19,18 +19,22 @@ func newEntry(source func() string) *Entry {
|
|||
}
|
||||
}
|
||||
|
||||
func (self *Entry) Enable() {
|
||||
self.active = true
|
||||
// Enable enables the entry.
|
||||
func (e *Entry) Enable() {
|
||||
e.active = true
|
||||
}
|
||||
|
||||
func (self *Entry) Disable() {
|
||||
self.active = false
|
||||
// Disable disables the entry.
|
||||
func (e *Entry) Disable() {
|
||||
e.active = false
|
||||
}
|
||||
|
||||
func (self Entry) Source() string {
|
||||
return self.source()
|
||||
// Source returns the source of the entry.
|
||||
func (e Entry) Source() string {
|
||||
return e.source()
|
||||
}
|
||||
|
||||
// Apply applies callback to all registry entries.
|
||||
func Apply(callback func(Entry)) {
|
||||
for _, entry := range registry {
|
||||
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 {
|
||||
entry := newEntry(source)
|
||||
registry = append(registry, entry)
|
||||
|
|
20
v1/vendor/github.com/robertkrimen/otto/result.go
generated
vendored
|
@ -1,28 +1,28 @@
|
|||
package otto
|
||||
|
||||
type _resultKind int
|
||||
type resultKind int
|
||||
|
||||
const (
|
||||
_ _resultKind = iota
|
||||
_ resultKind = iota
|
||||
resultReturn
|
||||
resultBreak
|
||||
resultContinue
|
||||
)
|
||||
|
||||
type _result struct {
|
||||
kind _resultKind
|
||||
type result struct {
|
||||
kind resultKind
|
||||
value Value
|
||||
target string
|
||||
}
|
||||
|
||||
func newReturnResult(value Value) _result {
|
||||
return _result{resultReturn, value, ""}
|
||||
func newReturnResult(value Value) result {
|
||||
return result{resultReturn, value, ""}
|
||||
}
|
||||
|
||||
func newContinueResult(target string) _result {
|
||||
return _result{resultContinue, emptyValue, target}
|
||||
func newContinueResult(target string) result {
|
||||
return result{resultContinue, emptyValue, target}
|
||||
}
|
||||
|
||||
func newBreakResult(target string) _result {
|
||||
return _result{resultBreak, emptyValue, target}
|
||||
func newBreakResult(target string) result {
|
||||
return result{resultBreak, emptyValue, target}
|
||||
}
|
||||
|
|
413
v1/vendor/github.com/robertkrimen/otto/runtime.go
generated
vendored
|
@ -8,7 +8,7 @@ import (
|
|||
"math"
|
||||
"path"
|
||||
"reflect"
|
||||
"runtime"
|
||||
goruntime "runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
@ -17,49 +17,49 @@ import (
|
|||
"github.com/robertkrimen/otto/parser"
|
||||
)
|
||||
|
||||
type _global struct {
|
||||
Object *_object // Object( ... ), new Object( ... ) - 1 (length)
|
||||
Function *_object // Function( ... ), new Function( ... ) - 1
|
||||
Array *_object // Array( ... ), new Array( ... ) - 1
|
||||
String *_object // String( ... ), new String( ... ) - 1
|
||||
Boolean *_object // Boolean( ... ), new Boolean( ... ) - 1
|
||||
Number *_object // Number( ... ), new Number( ... ) - 1
|
||||
Math *_object
|
||||
Date *_object // Date( ... ), new Date( ... ) - 7
|
||||
RegExp *_object // RegExp( ... ), new RegExp( ... ) - 2
|
||||
Error *_object // Error( ... ), new Error( ... ) - 1
|
||||
EvalError *_object
|
||||
TypeError *_object
|
||||
RangeError *_object
|
||||
ReferenceError *_object
|
||||
SyntaxError *_object
|
||||
URIError *_object
|
||||
JSON *_object
|
||||
type global struct {
|
||||
Object *object // Object( ... ), new Object( ... ) - 1 (length)
|
||||
Function *object // Function( ... ), new Function( ... ) - 1
|
||||
Array *object // Array( ... ), new Array( ... ) - 1
|
||||
String *object // String( ... ), new String( ... ) - 1
|
||||
Boolean *object // Boolean( ... ), new Boolean( ... ) - 1
|
||||
Number *object // Number( ... ), new Number( ... ) - 1
|
||||
Math *object
|
||||
Date *object // Date( ... ), new Date( ... ) - 7
|
||||
RegExp *object // RegExp( ... ), new RegExp( ... ) - 2
|
||||
Error *object // Error( ... ), new Error( ... ) - 1
|
||||
EvalError *object
|
||||
TypeError *object
|
||||
RangeError *object
|
||||
ReferenceError *object
|
||||
SyntaxError *object
|
||||
URIError *object
|
||||
JSON *object
|
||||
|
||||
ObjectPrototype *_object // Object.prototype
|
||||
FunctionPrototype *_object // Function.prototype
|
||||
ArrayPrototype *_object // Array.prototype
|
||||
StringPrototype *_object // String.prototype
|
||||
BooleanPrototype *_object // Boolean.prototype
|
||||
NumberPrototype *_object // Number.prototype
|
||||
DatePrototype *_object // Date.prototype
|
||||
RegExpPrototype *_object // RegExp.prototype
|
||||
ErrorPrototype *_object // Error.prototype
|
||||
EvalErrorPrototype *_object
|
||||
TypeErrorPrototype *_object
|
||||
RangeErrorPrototype *_object
|
||||
ReferenceErrorPrototype *_object
|
||||
SyntaxErrorPrototype *_object
|
||||
URIErrorPrototype *_object
|
||||
ObjectPrototype *object // Object.prototype
|
||||
FunctionPrototype *object // Function.prototype
|
||||
ArrayPrototype *object // Array.prototype
|
||||
StringPrototype *object // String.prototype
|
||||
BooleanPrototype *object // Boolean.prototype
|
||||
NumberPrototype *object // Number.prototype
|
||||
DatePrototype *object // Date.prototype
|
||||
RegExpPrototype *object // RegExp.prototype
|
||||
ErrorPrototype *object // Error.prototype
|
||||
EvalErrorPrototype *object
|
||||
TypeErrorPrototype *object
|
||||
RangeErrorPrototype *object
|
||||
ReferenceErrorPrototype *object
|
||||
SyntaxErrorPrototype *object
|
||||
URIErrorPrototype *object
|
||||
}
|
||||
|
||||
type _runtime struct {
|
||||
global _global
|
||||
globalObject *_object
|
||||
globalStash *_objectStash
|
||||
scope *_scope
|
||||
type runtime struct {
|
||||
global global
|
||||
globalObject *object
|
||||
globalStash *objectStash
|
||||
scope *scope
|
||||
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)
|
||||
random func() float64
|
||||
stackLimit int
|
||||
|
@ -69,54 +69,54 @@ type _runtime struct {
|
|||
lck sync.Mutex
|
||||
}
|
||||
|
||||
func (self *_runtime) enterScope(scope *_scope) {
|
||||
scope.outer = self.scope
|
||||
if self.scope != nil {
|
||||
if self.stackLimit != 0 && self.scope.depth+1 >= self.stackLimit {
|
||||
panic(self.panicRangeError("Maximum call stack size exceeded"))
|
||||
func (rt *runtime) enterScope(scop *scope) {
|
||||
scop.outer = rt.scope
|
||||
if rt.scope != nil {
|
||||
if rt.stackLimit != 0 && rt.scope.depth+1 >= rt.stackLimit {
|
||||
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() {
|
||||
self.scope = self.scope.outer
|
||||
func (rt *runtime) leaveScope() {
|
||||
rt.scope = rt.scope.outer
|
||||
}
|
||||
|
||||
// FIXME This is used in two places (cloning)
|
||||
func (self *_runtime) enterGlobalScope() {
|
||||
self.enterScope(newScope(self.globalStash, self.globalStash, self.globalObject))
|
||||
// FIXME This is used in two places (cloning).
|
||||
func (rt *runtime) enterGlobalScope() {
|
||||
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 {
|
||||
outer = self.globalStash
|
||||
outer = rt.globalStash
|
||||
}
|
||||
stash := self.newFunctionStash(outer)
|
||||
var thisObject *_object
|
||||
stash := rt.newFunctionStash(outer)
|
||||
var thisObject *object
|
||||
switch this.kind {
|
||||
case valueUndefined, valueNull:
|
||||
thisObject = self.globalObject
|
||||
thisObject = rt.globalObject
|
||||
default:
|
||||
thisObject = self.toObject(this)
|
||||
thisObject = rt.toObject(this)
|
||||
}
|
||||
self.enterScope(newScope(stash, stash, thisObject))
|
||||
rt.enterScope(newScope(stash, stash, thisObject))
|
||||
return stash
|
||||
}
|
||||
|
||||
func (self *_runtime) putValue(reference _reference, value Value) {
|
||||
func (rt *runtime) putValue(reference referencer, value Value) {
|
||||
name := reference.putValue(value)
|
||||
if name != "" {
|
||||
// Why? -- If reference.base == nil
|
||||
// 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)
|
||||
// throw = Something 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.
|
||||
defer func() {
|
||||
if caught := recover(); caught != nil {
|
||||
if exception, ok := caught.(*_exception); ok {
|
||||
caught = exception.eject()
|
||||
if excep, ok := caught.(*exception); ok {
|
||||
caught = excep.eject()
|
||||
}
|
||||
switch caught := caught.(type) {
|
||||
case _error:
|
||||
exception = true
|
||||
tryValue = toValue_object(self.newErrorObjectError(caught))
|
||||
case ottoError:
|
||||
isException = true
|
||||
tryValue = objectValue(rt.newErrorObjectError(caught))
|
||||
case Value:
|
||||
exception = true
|
||||
isException = true
|
||||
tryValue = caught
|
||||
default:
|
||||
exception = true
|
||||
isException = true
|
||||
tryValue = toValue(caught)
|
||||
}
|
||||
}
|
||||
|
@ -144,52 +144,51 @@ func (self *_runtime) tryCatchEvaluate(inner func() Value) (tryValue Value, exce
|
|||
return inner(), false
|
||||
}
|
||||
|
||||
// toObject
|
||||
|
||||
func (self *_runtime) toObject(value Value) *_object {
|
||||
func (rt *runtime) toObject(value Value) *object {
|
||||
switch value.kind {
|
||||
case valueEmpty, valueUndefined, valueNull:
|
||||
panic(self.panicTypeError())
|
||||
panic(rt.panicTypeError("toObject unsupported kind %s", value.kind))
|
||||
case valueBoolean:
|
||||
return self.newBoolean(value)
|
||||
return rt.newBoolean(value)
|
||||
case valueString:
|
||||
return self.newString(value)
|
||||
return rt.newString(value)
|
||||
case valueNumber:
|
||||
return self.newNumber(value)
|
||||
return rt.newNumber(value)
|
||||
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 {
|
||||
case valueUndefined:
|
||||
return nil, errors.New("undefined")
|
||||
case valueNull:
|
||||
return nil, errors.New("null")
|
||||
case valueBoolean:
|
||||
return self.newBoolean(value), nil
|
||||
return rt.newBoolean(value), nil
|
||||
case valueString:
|
||||
return self.newString(value), nil
|
||||
return rt.newString(value), nil
|
||||
case valueNumber:
|
||||
return self.newNumber(value), nil
|
||||
return rt.newNumber(value), nil
|
||||
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)
|
||||
if !isObject && !mustCoerce {
|
||||
panic(rt.panicTypeError())
|
||||
panic(rt.panicTypeError("checkObjectCoercible not object or mustCoerce"))
|
||||
}
|
||||
}
|
||||
|
||||
// testObjectCoercible
|
||||
|
||||
func testObjectCoercible(value Value) (isObject bool, mustCoerce bool) {
|
||||
// testObjectCoercible.
|
||||
func testObjectCoercible(value Value) (isObject, mustCoerce bool) { //nolint: nonamedreturns
|
||||
switch value.kind {
|
||||
case valueReference, valueEmpty, valueNull, valueUndefined:
|
||||
return false, false
|
||||
|
@ -198,21 +197,21 @@ func testObjectCoercible(value Value) (isObject bool, mustCoerce bool) {
|
|||
case valueObject:
|
||||
return true, false
|
||||
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{}
|
||||
err := catchPanic(func() {
|
||||
result = self.toValue(value)
|
||||
result = rt.toValue(value)
|
||||
})
|
||||
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.
|
||||
// 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())
|
||||
|
||||
if val.Kind() == t.Kind() {
|
||||
|
@ -231,20 +230,20 @@ func (self *_runtime) convertNumeric(v Value, t reflect.Type) reflect.Value {
|
|||
return reflect.ValueOf(f64)
|
||||
case reflect.Float32:
|
||||
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)
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
i64 := int64(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
|
||||
val = reflect.ValueOf(i64)
|
||||
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() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
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)
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
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)) {
|
||||
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)
|
||||
case reflect.Float32, reflect.Float64:
|
||||
|
@ -274,12 +273,12 @@ func (self *_runtime) convertNumeric(v Value, t reflect.Type) reflect.Value {
|
|||
switch t.Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
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)
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
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)
|
||||
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 {
|
||||
|
@ -332,13 +331,15 @@ func fieldIndexByName(t reflect.Type, name string) []int {
|
|||
return nil
|
||||
}
|
||||
|
||||
var typeOfValue = reflect.TypeOf(Value{})
|
||||
var typeOfJSONRawMessage = reflect.TypeOf(json.RawMessage{})
|
||||
var (
|
||||
typeOfValue = reflect.TypeOf(Value{})
|
||||
typeOfJSONRawMessage = reflect.TypeOf(json.RawMessage{})
|
||||
)
|
||||
|
||||
// convertCallParameter converts request val to type t if possible.
|
||||
// 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.
|
||||
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 {
|
||||
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 gso, ok := v._object().value.(*_goStructObject); ok {
|
||||
if gso, ok := v.object().value.(*goStructObject); ok {
|
||||
if gso.value.Type().AssignableTo(t) {
|
||||
// please see TestDynamicFunctionReturningInterface for why this exists
|
||||
if t.Kind() == reflect.Interface && gso.value.Type().ConvertibleTo(t) {
|
||||
return gso.value.Convert(t), nil
|
||||
} else {
|
||||
}
|
||||
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) {
|
||||
// please see TestDynamicFunctionReturningInterface for why this exists
|
||||
if t.Kind() == reflect.Interface && gao.value.Type().ConvertibleTo(t) {
|
||||
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
|
||||
default:
|
||||
var vv reflect.Value
|
||||
vv, err := self.convertCallParameter(v, t.Elem())
|
||||
vv, err := rt.convertCallParameter(v, t.Elem())
|
||||
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() {
|
||||
|
@ -418,12 +417,11 @@ func (self *_runtime) convertCallParameter(v Value, t reflect.Type) (reflect.Val
|
|||
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:
|
||||
switch v.kind {
|
||||
case valueNumber:
|
||||
return self.convertNumeric(v, t), nil
|
||||
if v.kind == valueNumber {
|
||||
return rt.convertNumeric(v, t), nil
|
||||
}
|
||||
case reflect.Slice:
|
||||
if o := v._object(); o != nil {
|
||||
if o := v.object(); o != nil {
|
||||
if lv := o.get(propertyLength); lv.IsNumber() {
|
||||
l := lv.number().int64
|
||||
|
||||
|
@ -432,7 +430,7 @@ func (self *_runtime) convertCallParameter(v Value, t reflect.Type) (reflect.Val
|
|||
tt := t.Elem()
|
||||
|
||||
switch o.class {
|
||||
case classArray:
|
||||
case classArrayName:
|
||||
for i := int64(0); i < l; i++ {
|
||||
p, ok := o.property[strconv.FormatInt(i, 10)]
|
||||
if !ok {
|
||||
|
@ -444,24 +442,24 @@ func (self *_runtime) convertCallParameter(v Value, t reflect.Type) (reflect.Val
|
|||
continue
|
||||
}
|
||||
|
||||
ev, err := self.convertCallParameter(e, tt)
|
||||
ev, err := rt.convertCallParameter(e, tt)
|
||||
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)
|
||||
}
|
||||
case classGoArray, classGoSlice:
|
||||
case classGoArrayName, classGoSliceName:
|
||||
var gslice bool
|
||||
switch o.value.(type) {
|
||||
case *_goSliceObject:
|
||||
case *goSliceObject:
|
||||
gslice = true
|
||||
case *_goArrayObject:
|
||||
case *goArrayObject:
|
||||
gslice = false
|
||||
}
|
||||
|
||||
for i := int64(0); i < l; i++ {
|
||||
var p *_property
|
||||
var p *property
|
||||
if gslice {
|
||||
p = goSliceGetOwnProperty(o, strconv.FormatInt(i, 10))
|
||||
} else {
|
||||
|
@ -476,9 +474,9 @@ func (self *_runtime) convertCallParameter(v Value, t reflect.Type) (reflect.Val
|
|||
continue
|
||||
}
|
||||
|
||||
ev, err := self.convertCallParameter(e, tt)
|
||||
ev, err := rt.convertCallParameter(e, tt)
|
||||
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)
|
||||
|
@ -489,15 +487,15 @@ func (self *_runtime) convertCallParameter(v Value, t reflect.Type) (reflect.Val
|
|||
}
|
||||
}
|
||||
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)
|
||||
|
||||
var err error
|
||||
|
||||
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 {
|
||||
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
|
||||
}
|
||||
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")
|
||||
}
|
||||
|
||||
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 {
|
||||
l := make([]interface{}, len(args))
|
||||
for i, a := range args {
|
||||
|
@ -533,16 +531,16 @@ func (self *_runtime) convertCallParameter(v Value, t reflect.Type) (reflect.Val
|
|||
return nil
|
||||
}
|
||||
|
||||
r, err := self.convertCallParameter(rv, t.Out(0))
|
||||
r, err := rt.convertCallParameter(rv, t.Out(0))
|
||||
if err != nil {
|
||||
panic(self.panicTypeError(err.Error()))
|
||||
panic(rt.panicTypeError("convertCallParameter Func: %s", err))
|
||||
}
|
||||
|
||||
return []reflect.Value{r}
|
||||
}), nil
|
||||
}
|
||||
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)
|
||||
|
||||
for _, k := range o.propertyOrder {
|
||||
|
@ -570,9 +568,9 @@ func (self *_runtime) convertCallParameter(v Value, t reflect.Type) (reflect.Val
|
|||
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 {
|
||||
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)
|
||||
|
@ -583,16 +581,16 @@ func (self *_runtime) convertCallParameter(v Value, t reflect.Type) (reflect.Val
|
|||
}
|
||||
|
||||
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() {
|
||||
sv, err := fn.Call(v)
|
||||
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 {
|
||||
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
|
||||
}
|
||||
|
@ -608,7 +606,7 @@ func (self *_runtime) convertCallParameter(v Value, t reflect.Type) (reflect.Val
|
|||
r := reflect.New(t)
|
||||
|
||||
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
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
func (self *_runtime) toValue(value interface{}) Value {
|
||||
func (rt *runtime) toValue(value interface{}) Value {
|
||||
rv, ok := value.(reflect.Value)
|
||||
if ok {
|
||||
value = rv.Interface()
|
||||
|
@ -647,58 +645,57 @@ func (self *_runtime) toValue(value interface{}) Value {
|
|||
var name, file string
|
||||
var line int
|
||||
pc := reflect.ValueOf(value).Pointer()
|
||||
fn := runtime.FuncForPC(pc)
|
||||
fn := goruntime.FuncForPC(pc)
|
||||
if fn != nil {
|
||||
name = fn.Name()
|
||||
file, line = fn.FileLine(pc)
|
||||
file = path.Base(file)
|
||||
}
|
||||
return toValue_object(self.newNativeFunction(name, file, line, value))
|
||||
case _nativeFunction:
|
||||
return objectValue(rt.newNativeFunction(name, file, line, value))
|
||||
case nativeFunction:
|
||||
var name, file string
|
||||
var line int
|
||||
pc := reflect.ValueOf(value).Pointer()
|
||||
fn := runtime.FuncForPC(pc)
|
||||
fn := goruntime.FuncForPC(pc)
|
||||
if fn != nil {
|
||||
name = fn.Name()
|
||||
file, line = fn.FileLine(pc)
|
||||
file = path.Base(file)
|
||||
}
|
||||
return toValue_object(self.newNativeFunction(name, file, line, value))
|
||||
case Object, *Object, _object, *_object:
|
||||
return objectValue(rt.newNativeFunction(name, file, line, value))
|
||||
case Object, *Object, object, *object:
|
||||
// Nothing happens.
|
||||
// FIXME We should really figure out what can come here.
|
||||
// This catch-all is ugly.
|
||||
default:
|
||||
{
|
||||
value := reflect.ValueOf(value)
|
||||
if ok && value.Kind() == rv.Kind() {
|
||||
val := reflect.ValueOf(value)
|
||||
if ok && val.Kind() == rv.Kind() {
|
||||
// Use passed in rv which may be writable.
|
||||
value = rv
|
||||
val = rv
|
||||
}
|
||||
|
||||
switch value.Kind() {
|
||||
switch val.Kind() {
|
||||
case reflect.Ptr:
|
||||
switch reflect.Indirect(value).Kind() {
|
||||
switch reflect.Indirect(val).Kind() {
|
||||
case reflect.Struct:
|
||||
return toValue_object(self.newGoStructObject(value))
|
||||
return objectValue(rt.newGoStructObject(val))
|
||||
case reflect.Array:
|
||||
return toValue_object(self.newGoArray(value))
|
||||
return objectValue(rt.newGoArray(val))
|
||||
}
|
||||
case reflect.Struct:
|
||||
return toValue_object(self.newGoStructObject(value))
|
||||
return objectValue(rt.newGoStructObject(val))
|
||||
case reflect.Map:
|
||||
return toValue_object(self.newGoMapObject(value))
|
||||
return objectValue(rt.newGoMapObject(val))
|
||||
case reflect.Slice:
|
||||
return toValue_object(self.newGoSlice(value))
|
||||
return objectValue(rt.newGoSlice(val))
|
||||
case reflect.Array:
|
||||
return toValue_object(self.newGoArray(value))
|
||||
return objectValue(rt.newGoArray(val))
|
||||
case reflect.Func:
|
||||
var name, file string
|
||||
var line int
|
||||
if v := reflect.ValueOf(value); v.Kind() == reflect.Ptr {
|
||||
if v := reflect.ValueOf(val); v.Kind() == reflect.Ptr {
|
||||
pc := v.Pointer()
|
||||
fn := runtime.FuncForPC(pc)
|
||||
fn := goruntime.FuncForPC(pc)
|
||||
if fn != nil {
|
||||
name = fn.Name()
|
||||
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()
|
||||
|
||||
if len(c.ArgumentList) != nargs {
|
||||
if typ.IsVariadic() {
|
||||
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 {
|
||||
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
|
||||
// out of the loop.
|
||||
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
|
||||
callSlice = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
v, err := self.convertCallParameter(a, t)
|
||||
v, err := rt.convertCallParameter(a, t)
|
||||
if err != nil {
|
||||
panic(self.panicTypeError(err.Error()))
|
||||
panic(rt.panicTypeError(err.Error()))
|
||||
}
|
||||
|
||||
in[i] = v
|
||||
|
@ -762,58 +759,57 @@ func (self *_runtime) toValue(value interface{}) Value {
|
|||
|
||||
var out []reflect.Value
|
||||
if callSlice {
|
||||
out = value.CallSlice(in)
|
||||
out = val.CallSlice(in)
|
||||
} else {
|
||||
out = value.Call(in)
|
||||
out = val.Call(in)
|
||||
}
|
||||
|
||||
switch len(out) {
|
||||
case 0:
|
||||
return Value{}
|
||||
case 1:
|
||||
return self.toValue(out[0].Interface())
|
||||
return rt.toValue(out[0].Interface())
|
||||
default:
|
||||
s := make([]interface{}, len(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)
|
||||
}
|
||||
|
||||
func (runtime *_runtime) newGoSlice(value reflect.Value) *_object {
|
||||
self := runtime.newGoSliceObject(value)
|
||||
self.prototype = runtime.global.ArrayPrototype
|
||||
return self
|
||||
func (rt *runtime) newGoSlice(value reflect.Value) *object {
|
||||
obj := rt.newGoSliceObject(value)
|
||||
obj.prototype = rt.global.ArrayPrototype
|
||||
return obj
|
||||
}
|
||||
|
||||
func (runtime *_runtime) newGoArray(value reflect.Value) *_object {
|
||||
self := runtime.newGoArrayObject(value)
|
||||
self.prototype = runtime.global.ArrayPrototype
|
||||
return self
|
||||
func (rt *runtime) newGoArray(value reflect.Value) *object {
|
||||
obj := rt.newGoArrayObject(value)
|
||||
obj.prototype = rt.global.ArrayPrototype
|
||||
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)
|
||||
}
|
||||
|
||||
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)
|
||||
if err != nil {
|
||||
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) {
|
||||
case *ast.Program:
|
||||
return nil, src, nil
|
||||
|
@ -821,22 +817,22 @@ func (self *_runtime) parseSource(src, sm interface{}) (*_nodeProgram, *ast.Prog
|
|||
return src.program, nil, nil
|
||||
}
|
||||
|
||||
program, err := self.parse("", src, sm)
|
||||
program, err := rt.parse("", src, sm)
|
||||
|
||||
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{}
|
||||
cmpl_program, program, err := self.parseSource(src, sm)
|
||||
node, program, err := rt.parseSource(src, sm)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
if cmpl_program == nil {
|
||||
cmpl_program = cmpl_parse(program)
|
||||
if node == nil {
|
||||
node = cmplParse(program)
|
||||
}
|
||||
err = catchPanic(func() {
|
||||
result = self.cmpl_evaluate_nodeProgram(cmpl_program, eval)
|
||||
result = rt.cmplEvaluateNodeProgram(node, eval)
|
||||
})
|
||||
switch result.kind {
|
||||
case valueEmpty:
|
||||
|
@ -847,33 +843,32 @@ func (self *_runtime) cmpl_runOrEval(src, sm interface{}, eval bool) (Value, err
|
|||
return result, err
|
||||
}
|
||||
|
||||
func (self *_runtime) cmpl_run(src, sm interface{}) (Value, error) {
|
||||
return self.cmpl_runOrEval(src, sm, false)
|
||||
func (rt *runtime) cmplRun(src, sm interface{}) (Value, error) {
|
||||
return rt.cmplRunOrEval(src, sm, false)
|
||||
}
|
||||
|
||||
func (self *_runtime) cmpl_eval(src, sm interface{}) (Value, error) {
|
||||
return self.cmpl_runOrEval(src, sm, true)
|
||||
func (rt *runtime) cmplEval(src, sm interface{}) (Value, error) {
|
||||
return rt.cmplRunOrEval(src, sm, true)
|
||||
}
|
||||
|
||||
func (self *_runtime) parseThrow(err error) {
|
||||
func (rt *runtime) parseThrow(err error) {
|
||||
if err == nil {
|
||||
return
|
||||
}
|
||||
switch err := err.(type) {
|
||||
case parser.ErrorList:
|
||||
{
|
||||
err := err[0]
|
||||
if err.Message == "Invalid left-hand side in assignment" {
|
||||
panic(self.panicReferenceError(err.Message))
|
||||
|
||||
var errl parser.ErrorList
|
||||
if errors.Is(err, &errl) {
|
||||
err := errl[0]
|
||||
if err.Message == "invalid left-hand side in assignment" {
|
||||
panic(rt.panicReferenceError(err.Message))
|
||||
}
|
||||
panic(self.panicSyntaxError(err.Message))
|
||||
panic(rt.panicSyntaxError(err.Message))
|
||||
}
|
||||
}
|
||||
panic(self.panicSyntaxError(err.Error()))
|
||||
panic(rt.panicSyntaxError(err.Error()))
|
||||
}
|
||||
|
||||
func (self *_runtime) cmpl_parseOrThrow(src, sm interface{}) *_nodeProgram {
|
||||
program, err := self.cmpl_parse("", src, sm)
|
||||
self.parseThrow(err) // Will panic/throw appropriately
|
||||
func (rt *runtime) cmplParseOrThrow(src, sm interface{}) *nodeProgram {
|
||||
program, err := rt.cmplParse("", src, sm)
|
||||
rt.parseThrow(err) // Will panic/throw appropriately
|
||||
return program
|
||||
}
|
||||
|
|
32
v1/vendor/github.com/robertkrimen/otto/scope.go
generated
vendored
|
@ -1,33 +1,19 @@
|
|||
package otto
|
||||
|
||||
// _scope:
|
||||
// entryFile
|
||||
// entryIdx
|
||||
// top?
|
||||
// outer => nil
|
||||
|
||||
// _stash:
|
||||
// lexical
|
||||
// variable
|
||||
//
|
||||
// _thisStash (ObjectEnvironment)
|
||||
// _fnStash
|
||||
// _dclStash
|
||||
|
||||
// An ECMA-262 ExecutionContext
|
||||
type _scope struct {
|
||||
lexical _stash
|
||||
variable _stash
|
||||
this *_object
|
||||
// An ECMA-262 ExecutionContext.
|
||||
type scope struct {
|
||||
lexical stasher
|
||||
variable stasher
|
||||
this *object
|
||||
eval bool // Replace this with kind?
|
||||
outer *_scope
|
||||
outer *scope
|
||||
depth int
|
||||
|
||||
frame _frame
|
||||
frame frame
|
||||
}
|
||||
|
||||
func newScope(lexical _stash, variable _stash, this *_object) *_scope {
|
||||
return &_scope{
|
||||
func newScope(lexical stasher, variable stasher, this *object) *scope {
|
||||
return &scope{
|
||||
lexical: lexical,
|
||||
variable: variable,
|
||||
this: this,
|
||||
|
|
50
v1/vendor/github.com/robertkrimen/otto/script.go
generated
vendored
|
@ -6,6 +6,7 @@ import (
|
|||
"errors"
|
||||
)
|
||||
|
||||
// ErrVersion is an error which represents a version mismatch.
|
||||
var ErrVersion = errors.New("version mismatch")
|
||||
|
||||
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.
|
||||
type Script struct {
|
||||
version string
|
||||
program *_nodeProgram
|
||||
program *nodeProgram
|
||||
filename string
|
||||
src string
|
||||
}
|
||||
|
@ -24,23 +25,22 @@ type Script struct {
|
|||
//
|
||||
// script, err := vm.Compile("", `var abc; if (!abc) abc = 0; abc += 2; abc;`)
|
||||
// vm.Run(script)
|
||||
func (self *Otto) Compile(filename string, src interface{}) (*Script, error) {
|
||||
return self.CompileWithSourceMap(filename, src, nil)
|
||||
func (o *Otto) Compile(filename string, src interface{}) (*Script, error) {
|
||||
return o.CompileWithSourceMap(filename, src, nil)
|
||||
}
|
||||
|
||||
// CompileWithSourceMap does the same thing as Compile, but with the obvious
|
||||
// difference of applying a source map.
|
||||
func (self *Otto) CompileWithSourceMap(filename string, src, sm interface{}) (*Script, error) {
|
||||
program, err := self.runtime.parse(filename, src, sm)
|
||||
func (o *Otto) CompileWithSourceMap(filename string, src, sm interface{}) (*Script, error) {
|
||||
program, err := o.runtime.parse(filename, src, sm)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cmpl_program := cmpl_parse(program)
|
||||
|
||||
node := cmplParse(program)
|
||||
script := &Script{
|
||||
version: scriptVersion,
|
||||
program: cmpl_program,
|
||||
program: node,
|
||||
filename: filename,
|
||||
src: program.File.Source(),
|
||||
}
|
||||
|
@ -48,30 +48,30 @@ func (self *Otto) CompileWithSourceMap(filename string, src, sm interface{}) (*S
|
|||
return script, nil
|
||||
}
|
||||
|
||||
func (self *Script) String() string {
|
||||
return "// " + self.filename + "\n" + self.src
|
||||
func (s *Script) String() string {
|
||||
return "// " + s.filename + "\n" + s.src
|
||||
}
|
||||
|
||||
// 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.
|
||||
//
|
||||
// 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
|
||||
encoder := gob.NewEncoder(&bfr)
|
||||
err := encoder.Encode(self.version)
|
||||
err := encoder.Encode(s.version)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = encoder.Encode(self.program)
|
||||
err = encoder.Encode(s.program)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = encoder.Encode(self.filename)
|
||||
err = encoder.Encode(s.filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = encoder.Encode(self.src)
|
||||
err = encoder.Encode(s.src)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -83,27 +83,27 @@ func (self *Script) marshalBinary() ([]byte, error) {
|
|||
// will return an error.
|
||||
//
|
||||
// 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))
|
||||
defer func() {
|
||||
if err != nil {
|
||||
self.version = ""
|
||||
self.program = nil
|
||||
self.filename = ""
|
||||
self.src = ""
|
||||
s.version = ""
|
||||
s.program = nil
|
||||
s.filename = ""
|
||||
s.src = ""
|
||||
}
|
||||
}()
|
||||
if err = decoder.Decode(&self.version); err != nil {
|
||||
if err = decoder.Decode(&s.version); err != nil {
|
||||
return err
|
||||
}
|
||||
if self.version != scriptVersion {
|
||||
if s.version != scriptVersion {
|
||||
return ErrVersion
|
||||
}
|
||||
if err = decoder.Decode(&self.program); err != nil {
|
||||
if err = decoder.Decode(&s.program); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = decoder.Decode(&self.filename); err != nil {
|
||||
if err = decoder.Decode(&s.filename); err != nil {
|
||||
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"
|
||||
)
|
||||
|
||||
// ======
|
||||
// _stash
|
||||
// ======
|
||||
|
||||
type _stash interface {
|
||||
// stasher is implemented by types which can stash data.
|
||||
type stasher interface {
|
||||
hasBinding(string) bool //
|
||||
createBinding(string, bool, Value) // CreateMutableBinding
|
||||
setBinding(string, Value, bool) // SetMutableBinding
|
||||
|
@ -16,160 +13,151 @@ type _stash interface {
|
|||
deleteBinding(string) bool //
|
||||
setValue(string, Value, bool) // createBinding + setBinding
|
||||
|
||||
outer() _stash
|
||||
runtime() *_runtime
|
||||
outer() stasher
|
||||
runtime() *runtime
|
||||
|
||||
newReference(string, bool, _at) _reference
|
||||
newReference(string, bool, at) referencer
|
||||
|
||||
clone(clone *_clone) _stash
|
||||
clone(*cloner) stasher
|
||||
}
|
||||
|
||||
// ==========
|
||||
// _objectStash
|
||||
// ==========
|
||||
|
||||
type _objectStash struct {
|
||||
_runtime *_runtime
|
||||
_outer _stash
|
||||
object *_object
|
||||
type objectStash struct {
|
||||
rt *runtime
|
||||
outr stasher
|
||||
object *object
|
||||
}
|
||||
|
||||
func (self *_objectStash) runtime() *_runtime {
|
||||
return self._runtime
|
||||
func (s *objectStash) runtime() *runtime {
|
||||
return s.rt
|
||||
}
|
||||
|
||||
func (runtime *_runtime) newObjectStash(object *_object, outer _stash) *_objectStash {
|
||||
if object == nil {
|
||||
object = runtime.newBaseObject()
|
||||
object.class = "environment"
|
||||
func (rt *runtime) newObjectStash(obj *object, outer stasher) *objectStash {
|
||||
if obj == nil {
|
||||
obj = rt.newBaseObject()
|
||||
obj.class = "environment"
|
||||
}
|
||||
return &_objectStash{
|
||||
_runtime: runtime,
|
||||
_outer: outer,
|
||||
object: object,
|
||||
return &objectStash{
|
||||
rt: rt,
|
||||
outr: outer,
|
||||
object: obj,
|
||||
}
|
||||
}
|
||||
|
||||
func (in *_objectStash) clone(clone *_clone) _stash {
|
||||
out, exists := clone.objectStash(in)
|
||||
func (s *objectStash) clone(c *cloner) stasher {
|
||||
out, exists := c.objectStash(s)
|
||||
if exists {
|
||||
return out
|
||||
}
|
||||
*out = _objectStash{
|
||||
clone.runtime,
|
||||
clone.stash(in._outer),
|
||||
clone.object(in.object),
|
||||
*out = objectStash{
|
||||
c.runtime,
|
||||
c.stash(s.outr),
|
||||
c.object(s.object),
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func (self *_objectStash) hasBinding(name string) bool {
|
||||
return self.object.hasProperty(name)
|
||||
func (s *objectStash) hasBinding(name string) bool {
|
||||
return s.object.hasProperty(name)
|
||||
}
|
||||
|
||||
func (self *_objectStash) createBinding(name string, deletable bool, value Value) {
|
||||
if self.object.hasProperty(name) {
|
||||
func (s *objectStash) createBinding(name string, deletable bool, value Value) {
|
||||
if s.object.hasProperty(name) {
|
||||
panic(hereBeDragons())
|
||||
}
|
||||
mode := _propertyMode(0111)
|
||||
mode := propertyMode(0o111)
|
||||
if !deletable {
|
||||
mode = _propertyMode(0110)
|
||||
mode = propertyMode(0o110)
|
||||
}
|
||||
// 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) {
|
||||
self.object.put(name, value, strict)
|
||||
func (s *objectStash) setBinding(name string, value Value, strict bool) {
|
||||
s.object.put(name, value, strict)
|
||||
}
|
||||
|
||||
func (self *_objectStash) setValue(name string, value Value, throw bool) {
|
||||
if !self.hasBinding(name) {
|
||||
self.createBinding(name, true, value) // Configurable by default
|
||||
func (s *objectStash) setValue(name string, value Value, throw bool) {
|
||||
if !s.hasBinding(name) {
|
||||
s.createBinding(name, true, value) // Configurable by default
|
||||
} else {
|
||||
self.setBinding(name, value, throw)
|
||||
s.setBinding(name, value, throw)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *_objectStash) getBinding(name string, throw bool) Value {
|
||||
if self.object.hasProperty(name) {
|
||||
return self.object.get(name)
|
||||
func (s *objectStash) getBinding(name string, throw bool) Value {
|
||||
if s.object.hasProperty(name) {
|
||||
return s.object.get(name)
|
||||
}
|
||||
if throw { // strict?
|
||||
panic(self._runtime.panicReferenceError("Not Defined", name))
|
||||
panic(s.rt.panicReferenceError("Not Defined", name))
|
||||
}
|
||||
return Value{}
|
||||
}
|
||||
|
||||
func (self *_objectStash) deleteBinding(name string) bool {
|
||||
return self.object.delete(name, false)
|
||||
func (s *objectStash) deleteBinding(name string) bool {
|
||||
return s.object.delete(name, false)
|
||||
}
|
||||
|
||||
func (self *_objectStash) outer() _stash {
|
||||
return self._outer
|
||||
func (s *objectStash) outer() stasher {
|
||||
return s.outr
|
||||
}
|
||||
|
||||
func (self *_objectStash) newReference(name string, strict bool, at _at) _reference {
|
||||
return newPropertyReference(self._runtime, self.object, name, strict, at)
|
||||
func (s *objectStash) newReference(name string, strict bool, atv at) referencer {
|
||||
return newPropertyReference(s.rt, s.object, name, strict, atv)
|
||||
}
|
||||
|
||||
// =========
|
||||
// _dclStash
|
||||
// =========
|
||||
|
||||
type _dclStash struct {
|
||||
_runtime *_runtime
|
||||
_outer _stash
|
||||
property map[string]_dclProperty
|
||||
type dclStash struct {
|
||||
rt *runtime
|
||||
outr stasher
|
||||
property map[string]dclProperty
|
||||
}
|
||||
|
||||
type _dclProperty struct {
|
||||
type dclProperty struct {
|
||||
value Value
|
||||
mutable bool
|
||||
deletable bool
|
||||
readable bool
|
||||
}
|
||||
|
||||
func (runtime *_runtime) newDeclarationStash(outer _stash) *_dclStash {
|
||||
return &_dclStash{
|
||||
_runtime: runtime,
|
||||
_outer: outer,
|
||||
property: map[string]_dclProperty{},
|
||||
func (rt *runtime) newDeclarationStash(outer stasher) *dclStash {
|
||||
return &dclStash{
|
||||
rt: rt,
|
||||
outr: outer,
|
||||
property: map[string]dclProperty{},
|
||||
}
|
||||
}
|
||||
|
||||
func (in *_dclStash) clone(clone *_clone) _stash {
|
||||
out, exists := clone.dclStash(in)
|
||||
func (s *dclStash) clone(c *cloner) stasher {
|
||||
out, exists := c.dclStash(s)
|
||||
if exists {
|
||||
return out
|
||||
}
|
||||
property := make(map[string]_dclProperty, len(in.property))
|
||||
for index, value := range in.property {
|
||||
property[index] = clone.dclProperty(value)
|
||||
prop := make(map[string]dclProperty, len(s.property))
|
||||
for index, value := range s.property {
|
||||
prop[index] = c.dclProperty(value)
|
||||
}
|
||||
*out = _dclStash{
|
||||
clone.runtime,
|
||||
clone.stash(in._outer),
|
||||
property,
|
||||
*out = dclStash{
|
||||
c.runtime,
|
||||
c.stash(s.outr),
|
||||
prop,
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func (self *_dclStash) hasBinding(name string) bool {
|
||||
_, exists := self.property[name]
|
||||
func (s *dclStash) hasBinding(name string) bool {
|
||||
_, exists := s.property[name]
|
||||
return exists
|
||||
}
|
||||
|
||||
func (self *_dclStash) runtime() *_runtime {
|
||||
return self._runtime
|
||||
func (s *dclStash) runtime() *runtime {
|
||||
return s.rt
|
||||
}
|
||||
|
||||
func (self *_dclStash) createBinding(name string, deletable bool, value Value) {
|
||||
_, exists := self.property[name]
|
||||
if exists {
|
||||
func (s *dclStash) createBinding(name string, deletable bool, value Value) {
|
||||
if _, exists := s.property[name]; exists {
|
||||
panic(fmt.Errorf("createBinding: %s: already exists", name))
|
||||
}
|
||||
self.property[name] = _dclProperty{
|
||||
s.property[name] = dclProperty{
|
||||
value: value,
|
||||
mutable: true,
|
||||
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) {
|
||||
property, exists := self.property[name]
|
||||
func (s *dclStash) setBinding(name string, value Value, strict bool) {
|
||||
prop, exists := s.property[name]
|
||||
if !exists {
|
||||
panic(fmt.Errorf("setBinding: %s: missing", name))
|
||||
}
|
||||
if property.mutable {
|
||||
property.value = value
|
||||
self.property[name] = property
|
||||
if prop.mutable {
|
||||
prop.value = value
|
||||
s.property[name] = prop
|
||||
} else {
|
||||
self._runtime.typeErrorResult(strict)
|
||||
s.rt.typeErrorResult(strict)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *_dclStash) setValue(name string, value Value, throw bool) {
|
||||
if !self.hasBinding(name) {
|
||||
self.createBinding(name, false, value) // NOT deletable by default
|
||||
func (s *dclStash) setValue(name string, value Value, throw bool) {
|
||||
if !s.hasBinding(name) {
|
||||
s.createBinding(name, false, value) // NOT deletable by default
|
||||
} else {
|
||||
self.setBinding(name, value, throw)
|
||||
s.setBinding(name, value, throw)
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME This is called a __lot__
|
||||
func (self *_dclStash) getBinding(name string, throw bool) Value {
|
||||
property, exists := self.property[name]
|
||||
// FIXME This is called a __lot__.
|
||||
func (s *dclStash) getBinding(name string, throw bool) Value {
|
||||
prop, exists := s.property[name]
|
||||
if !exists {
|
||||
panic(fmt.Errorf("getBinding: %s: missing", name))
|
||||
}
|
||||
if !property.mutable && !property.readable {
|
||||
if !prop.mutable && !prop.readable {
|
||||
if throw { // strict?
|
||||
panic(self._runtime.panicTypeError())
|
||||
panic(s.rt.panicTypeError("getBinding property %s not mutable and not readable", name))
|
||||
}
|
||||
return Value{}
|
||||
}
|
||||
return property.value
|
||||
return prop.value
|
||||
}
|
||||
|
||||
func (self *_dclStash) deleteBinding(name string) bool {
|
||||
property, exists := self.property[name]
|
||||
func (s *dclStash) deleteBinding(name string) bool {
|
||||
prop, exists := s.property[name]
|
||||
if !exists {
|
||||
return true
|
||||
}
|
||||
if !property.deletable {
|
||||
if !prop.deletable {
|
||||
return false
|
||||
}
|
||||
delete(self.property, name)
|
||||
delete(s.property, name)
|
||||
return true
|
||||
}
|
||||
|
||||
func (self *_dclStash) outer() _stash {
|
||||
return self._outer
|
||||
func (s *dclStash) outer() stasher {
|
||||
return s.outr
|
||||
}
|
||||
|
||||
func (self *_dclStash) newReference(name string, strict bool, _ _at) _reference {
|
||||
return &_stashReference{
|
||||
func (s *dclStash) newReference(name string, strict bool, _ at) referencer {
|
||||
return &stashReference{
|
||||
name: name,
|
||||
base: self,
|
||||
base: s,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -240,57 +228,62 @@ func (self *_dclStash) newReference(name string, strict bool, _ _at) _reference
|
|||
// _fnStash
|
||||
// ========
|
||||
|
||||
type _fnStash struct {
|
||||
_dclStash
|
||||
arguments *_object
|
||||
type fnStash struct {
|
||||
dclStash
|
||||
arguments *object
|
||||
indexOfArgumentName map[string]string
|
||||
}
|
||||
|
||||
func (runtime *_runtime) newFunctionStash(outer _stash) *_fnStash {
|
||||
return &_fnStash{
|
||||
_dclStash: _dclStash{
|
||||
_runtime: runtime,
|
||||
_outer: outer,
|
||||
property: map[string]_dclProperty{},
|
||||
func (rt *runtime) newFunctionStash(outer stasher) *fnStash {
|
||||
return &fnStash{
|
||||
dclStash: dclStash{
|
||||
rt: rt,
|
||||
outr: outer,
|
||||
property: map[string]dclProperty{},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (in *_fnStash) clone(clone *_clone) _stash {
|
||||
out, exists := clone.fnStash(in)
|
||||
func (s *fnStash) clone(c *cloner) stasher {
|
||||
out, exists := c.fnStash(s)
|
||||
if exists {
|
||||
return out
|
||||
}
|
||||
dclStash := in._dclStash.clone(clone).(*_dclStash)
|
||||
index := make(map[string]string, len(in.indexOfArgumentName))
|
||||
for name, value := range in.indexOfArgumentName {
|
||||
dclStash := s.dclStash.clone(c).(*dclStash)
|
||||
index := make(map[string]string, len(s.indexOfArgumentName))
|
||||
for name, value := range s.indexOfArgumentName {
|
||||
index[name] = value
|
||||
}
|
||||
*out = _fnStash{
|
||||
_dclStash: *dclStash,
|
||||
arguments: clone.object(in.arguments),
|
||||
*out = fnStash{
|
||||
dclStash: *dclStash,
|
||||
arguments: c.object(s.arguments),
|
||||
indexOfArgumentName: index,
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func getStashProperties(stash _stash) (keys []string) {
|
||||
// getStashProperties returns the properties from stash.
|
||||
func getStashProperties(stash stasher) []string {
|
||||
switch vars := stash.(type) {
|
||||
case *_dclStash:
|
||||
case *dclStash:
|
||||
keys := make([]string, 0, len(vars.property))
|
||||
for k := range vars.property {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
case *_fnStash:
|
||||
return keys
|
||||
case *fnStash:
|
||||
keys := make([]string, 0, len(vars.property))
|
||||
for k := range vars.property {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
case *_objectStash:
|
||||
return keys
|
||||
case *objectStash:
|
||||
keys := make([]string, 0, len(vars.object.property))
|
||||
for k := range vars.object.property {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
return keys
|
||||
default:
|
||||
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
|
58
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
|
||||
// name (e.g. for the token IDENTIFIER, the string is "IDENTIFIER").
|
||||
func (tkn Token) String() string {
|
||||
if 0 == tkn {
|
||||
switch {
|
||||
case tkn == 0:
|
||||
return "UNKNOWN"
|
||||
}
|
||||
if tkn < Token(len(token2string)) {
|
||||
case tkn < Token(len(token2string)):
|
||||
return token2string[tkn]
|
||||
}
|
||||
default:
|
||||
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
|
||||
futureKeyword 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
|
||||
|
||||
const (
|
||||
_ Token = iota
|
||||
|
||||
// Control.
|
||||
ILLEGAL
|
||||
EOF
|
||||
COMMENT
|
||||
KEYWORD
|
||||
|
||||
// Types.
|
||||
STRING
|
||||
BOOLEAN
|
||||
NULL
|
||||
NUMBER
|
||||
IDENTIFIER
|
||||
|
||||
// Maths.
|
||||
PLUS // +
|
||||
MINUS // -
|
||||
MULTIPLY // *
|
||||
SLASH // /
|
||||
REMAINDER // %
|
||||
|
||||
// Logical and bitwise operators.
|
||||
AND // &
|
||||
OR // |
|
||||
EXCLUSIVE_OR // ^
|
||||
|
@ -27,13 +30,13 @@ const (
|
|||
SHIFT_RIGHT // >>
|
||||
UNSIGNED_SHIFT_RIGHT // >>>
|
||||
AND_NOT // &^
|
||||
|
||||
// Math assignments.
|
||||
ADD_ASSIGN // +=
|
||||
SUBTRACT_ASSIGN // -=
|
||||
MULTIPLY_ASSIGN // *=
|
||||
QUOTIENT_ASSIGN // /=
|
||||
REMAINDER_ASSIGN // %=
|
||||
|
||||
// Math and bitwise assignments.
|
||||
AND_ASSIGN // &=
|
||||
OR_ASSIGN // |=
|
||||
EXCLUSIVE_OR_ASSIGN // ^=
|
||||
|
@ -41,74 +44,73 @@ const (
|
|||
SHIFT_RIGHT_ASSIGN // >>=
|
||||
UNSIGNED_SHIFT_RIGHT_ASSIGN // >>>=
|
||||
AND_NOT_ASSIGN // &^=
|
||||
|
||||
// Logical operators and decrement / increment.
|
||||
LOGICAL_AND // &&
|
||||
LOGICAL_OR // ||
|
||||
INCREMENT // ++
|
||||
DECREMENT // --
|
||||
|
||||
// Comparison operators.
|
||||
EQUAL // ==
|
||||
STRICT_EQUAL // ===
|
||||
LESS // <
|
||||
GREATER // >
|
||||
ASSIGN // =
|
||||
NOT // !
|
||||
|
||||
// Bitwise not.
|
||||
BITWISE_NOT // ~
|
||||
|
||||
// Comparison operators.
|
||||
NOT_EQUAL // !=
|
||||
STRICT_NOT_EQUAL // !==
|
||||
LESS_OR_EQUAL // <=
|
||||
GREATER_OR_EQUAL // >=
|
||||
|
||||
// Left operators.
|
||||
LEFT_PARENTHESIS // (
|
||||
LEFT_BRACKET // [
|
||||
LEFT_BRACE // {
|
||||
COMMA // ,
|
||||
PERIOD // .
|
||||
|
||||
// Right operators.
|
||||
RIGHT_PARENTHESIS // )
|
||||
RIGHT_BRACKET // ]
|
||||
RIGHT_BRACE // }
|
||||
SEMICOLON // ;
|
||||
COLON // :
|
||||
QUESTION_MARK // ?
|
||||
|
||||
firstKeyword //nolint: deadcode
|
||||
// Basic flow - keywords below here.
|
||||
_
|
||||
IF
|
||||
IN
|
||||
DO
|
||||
|
||||
// Declarations.
|
||||
VAR
|
||||
FOR
|
||||
NEW
|
||||
TRY
|
||||
|
||||
// Advanced flow.
|
||||
THIS
|
||||
ELSE
|
||||
CASE
|
||||
VOID
|
||||
WITH
|
||||
|
||||
// Loops.
|
||||
WHILE
|
||||
BREAK
|
||||
CATCH
|
||||
THROW
|
||||
|
||||
// Functions.
|
||||
RETURN
|
||||
TYPEOF
|
||||
DELETE
|
||||
SWITCH
|
||||
|
||||
// Fallback identifiers.
|
||||
DEFAULT
|
||||
FINALLY
|
||||
|
||||
// Miscellaneous.
|
||||
FUNCTION
|
||||
CONTINUE
|
||||
DEBUGGER
|
||||
|
||||
// Instance of.
|
||||
INSTANCEOF
|
||||
lastKeyword //nolint: deadcode
|
||||
)
|
||||
|
||||
var token2string = [...]string{
|
||||
|
@ -199,149 +201,149 @@ var token2string = [...]string{
|
|||
INSTANCEOF: "instanceof",
|
||||
}
|
||||
|
||||
var keywordTable = map[string]_keyword{
|
||||
"if": _keyword{
|
||||
var keywordTable = map[string]keyword{
|
||||
"if": {
|
||||
token: IF,
|
||||
},
|
||||
"in": _keyword{
|
||||
"in": {
|
||||
token: IN,
|
||||
},
|
||||
"do": _keyword{
|
||||
"do": {
|
||||
token: DO,
|
||||
},
|
||||
"var": _keyword{
|
||||
"var": {
|
||||
token: VAR,
|
||||
},
|
||||
"for": _keyword{
|
||||
"for": {
|
||||
token: FOR,
|
||||
},
|
||||
"new": _keyword{
|
||||
"new": {
|
||||
token: NEW,
|
||||
},
|
||||
"try": _keyword{
|
||||
"try": {
|
||||
token: TRY,
|
||||
},
|
||||
"this": _keyword{
|
||||
"this": {
|
||||
token: THIS,
|
||||
},
|
||||
"else": _keyword{
|
||||
"else": {
|
||||
token: ELSE,
|
||||
},
|
||||
"case": _keyword{
|
||||
"case": {
|
||||
token: CASE,
|
||||
},
|
||||
"void": _keyword{
|
||||
"void": {
|
||||
token: VOID,
|
||||
},
|
||||
"with": _keyword{
|
||||
"with": {
|
||||
token: WITH,
|
||||
},
|
||||
"while": _keyword{
|
||||
"while": {
|
||||
token: WHILE,
|
||||
},
|
||||
"break": _keyword{
|
||||
"break": {
|
||||
token: BREAK,
|
||||
},
|
||||
"catch": _keyword{
|
||||
"catch": {
|
||||
token: CATCH,
|
||||
},
|
||||
"throw": _keyword{
|
||||
"throw": {
|
||||
token: THROW,
|
||||
},
|
||||
"return": _keyword{
|
||||
"return": {
|
||||
token: RETURN,
|
||||
},
|
||||
"typeof": _keyword{
|
||||
"typeof": {
|
||||
token: TYPEOF,
|
||||
},
|
||||
"delete": _keyword{
|
||||
"delete": {
|
||||
token: DELETE,
|
||||
},
|
||||
"switch": _keyword{
|
||||
"switch": {
|
||||
token: SWITCH,
|
||||
},
|
||||
"default": _keyword{
|
||||
"default": {
|
||||
token: DEFAULT,
|
||||
},
|
||||
"finally": _keyword{
|
||||
"finally": {
|
||||
token: FINALLY,
|
||||
},
|
||||
"function": _keyword{
|
||||
"function": {
|
||||
token: FUNCTION,
|
||||
},
|
||||
"continue": _keyword{
|
||||
"continue": {
|
||||
token: CONTINUE,
|
||||
},
|
||||
"debugger": _keyword{
|
||||
"debugger": {
|
||||
token: DEBUGGER,
|
||||
},
|
||||
"instanceof": _keyword{
|
||||
"instanceof": {
|
||||
token: INSTANCEOF,
|
||||
},
|
||||
"const": _keyword{
|
||||
"const": {
|
||||
token: KEYWORD,
|
||||
futureKeyword: true,
|
||||
},
|
||||
"class": _keyword{
|
||||
"class": {
|
||||
token: KEYWORD,
|
||||
futureKeyword: true,
|
||||
},
|
||||
"enum": _keyword{
|
||||
"enum": {
|
||||
token: KEYWORD,
|
||||
futureKeyword: true,
|
||||
},
|
||||
"export": _keyword{
|
||||
"export": {
|
||||
token: KEYWORD,
|
||||
futureKeyword: true,
|
||||
},
|
||||
"extends": _keyword{
|
||||
"extends": {
|
||||
token: KEYWORD,
|
||||
futureKeyword: true,
|
||||
},
|
||||
"import": _keyword{
|
||||
"import": {
|
||||
token: KEYWORD,
|
||||
futureKeyword: true,
|
||||
},
|
||||
"super": _keyword{
|
||||
"super": {
|
||||
token: KEYWORD,
|
||||
futureKeyword: true,
|
||||
},
|
||||
"implements": _keyword{
|
||||
"implements": {
|
||||
token: KEYWORD,
|
||||
futureKeyword: true,
|
||||
strict: true,
|
||||
},
|
||||
"interface": _keyword{
|
||||
"interface": {
|
||||
token: KEYWORD,
|
||||
futureKeyword: true,
|
||||
strict: true,
|
||||
},
|
||||
"let": _keyword{
|
||||
"let": {
|
||||
token: KEYWORD,
|
||||
futureKeyword: true,
|
||||
strict: true,
|
||||
},
|
||||
"package": _keyword{
|
||||
"package": {
|
||||
token: KEYWORD,
|
||||
futureKeyword: true,
|
||||
strict: true,
|
||||
},
|
||||
"private": _keyword{
|
||||
"private": {
|
||||
token: KEYWORD,
|
||||
futureKeyword: true,
|
||||
strict: true,
|
||||
},
|
||||
"protected": _keyword{
|
||||
"protected": {
|
||||
token: KEYWORD,
|
||||
futureKeyword: true,
|
||||
strict: true,
|
||||
},
|
||||
"public": _keyword{
|
||||
"public": {
|
||||
token: KEYWORD,
|
||||
futureKeyword: true,
|
||||
strict: true,
|
||||
},
|
||||
"static": _keyword{
|
||||
"static": {
|
||||
token: KEYWORD,
|
||||
futureKeyword: 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"
|
||||
)
|
||||
|
||||
func (runtime *_runtime) newArgumentsObject(indexOfParameterName []string, stash _stash, length int) *_object {
|
||||
self := runtime.newClassObject("Arguments")
|
||||
func (rt *runtime) newArgumentsObject(indexOfParameterName []string, stash stasher, length int) *object {
|
||||
obj := rt.newClassObject("Arguments")
|
||||
|
||||
for index, _ := range indexOfParameterName {
|
||||
for index := range indexOfParameterName {
|
||||
name := strconv.FormatInt(int64(index), 10)
|
||||
objectDefineOwnProperty(self, name, _property{Value{}, 0111}, false)
|
||||
objectDefineOwnProperty(obj, name, property{Value{}, 0o111}, false)
|
||||
}
|
||||
|
||||
self.objectClass = _classArguments
|
||||
self.value = _argumentsObject{
|
||||
obj.objectClass = classArguments
|
||||
obj.value = argumentsObject{
|
||||
indexOfParameterName: indexOfParameterName,
|
||||
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
|
||||
// function(abc, def, ghi)
|
||||
// indexOfParameterName[0] = "abc"
|
||||
// indexOfParameterName[1] = "def"
|
||||
// indexOfParameterName[2] = "ghi"
|
||||
// ...
|
||||
stash _stash
|
||||
stash stasher
|
||||
}
|
||||
|
||||
func (in _argumentsObject) clone(clone *_clone) _argumentsObject {
|
||||
indexOfParameterName := make([]string, len(in.indexOfParameterName))
|
||||
copy(indexOfParameterName, in.indexOfParameterName)
|
||||
return _argumentsObject{
|
||||
func (o argumentsObject) clone(c *cloner) argumentsObject {
|
||||
indexOfParameterName := make([]string, len(o.indexOfParameterName))
|
||||
copy(indexOfParameterName, o.indexOfParameterName)
|
||||
return argumentsObject{
|
||||
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)
|
||||
if index >= 0 && index < int64(len(self.indexOfParameterName)) {
|
||||
name := self.indexOfParameterName[index]
|
||||
if index >= 0 && index < int64(len(o.indexOfParameterName)) {
|
||||
name := o.indexOfParameterName[index]
|
||||
if name == "" {
|
||||
return Value{}, false
|
||||
}
|
||||
return self.stash.getBinding(name, false), true
|
||||
return o.stash.getBinding(name, false), true
|
||||
}
|
||||
return Value{}, false
|
||||
}
|
||||
|
||||
func (self _argumentsObject) put(name string, value Value) {
|
||||
func (o argumentsObject) put(name string, value Value) {
|
||||
index := stringToArrayIndex(name)
|
||||
name = self.indexOfParameterName[index]
|
||||
self.stash.setBinding(name, value, false)
|
||||
name = o.indexOfParameterName[index]
|
||||
o.stash.setBinding(name, value, false)
|
||||
}
|
||||
|
||||
func (self _argumentsObject) delete(name string) {
|
||||
func (o argumentsObject) delete(name string) {
|
||||
index := stringToArrayIndex(name)
|
||||
self.indexOfParameterName[index] = ""
|
||||
o.indexOfParameterName[index] = ""
|
||||
}
|
||||
|
||||
func argumentsGet(self *_object, name string) Value {
|
||||
if value, exists := self.value.(_argumentsObject).get(name); exists {
|
||||
func argumentsGet(obj *object, name string) Value {
|
||||
if value, exists := obj.value.(argumentsObject).get(name); exists {
|
||||
return value
|
||||
}
|
||||
return objectGet(self, name)
|
||||
return objectGet(obj, name)
|
||||
}
|
||||
|
||||
func argumentsGetOwnProperty(self *_object, name string) *_property {
|
||||
property := objectGetOwnProperty(self, name)
|
||||
if value, exists := self.value.(_argumentsObject).get(name); exists {
|
||||
property.value = value
|
||||
func argumentsGetOwnProperty(obj *object, name string) *property {
|
||||
prop := objectGetOwnProperty(obj, name)
|
||||
if value, exists := obj.value.(argumentsObject).get(name); exists {
|
||||
prop.value = value
|
||||
}
|
||||
return property
|
||||
return prop
|
||||
}
|
||||
|
||||
func argumentsDefineOwnProperty(self *_object, name string, descriptor _property, throw bool) bool {
|
||||
if _, exists := self.value.(_argumentsObject).get(name); exists {
|
||||
if !objectDefineOwnProperty(self, name, descriptor, false) {
|
||||
return self.runtime.typeErrorResult(throw)
|
||||
func argumentsDefineOwnProperty(obj *object, name string, descriptor property, throw bool) bool {
|
||||
if _, exists := obj.value.(argumentsObject).get(name); exists {
|
||||
if !objectDefineOwnProperty(obj, name, descriptor, false) {
|
||||
return obj.runtime.typeErrorResult(throw)
|
||||
}
|
||||
if value, valid := descriptor.value.(Value); valid {
|
||||
self.value.(_argumentsObject).put(name, value)
|
||||
obj.value.(argumentsObject).put(name, value)
|
||||
}
|
||||
return true
|
||||
}
|
||||
return objectDefineOwnProperty(self, name, descriptor, throw)
|
||||
return objectDefineOwnProperty(obj, name, descriptor, throw)
|
||||
}
|
||||
|
||||
func argumentsDelete(self *_object, name string, throw bool) bool {
|
||||
if !objectDelete(self, name, throw) {
|
||||
func argumentsDelete(obj *object, name string, throw bool) bool {
|
||||
if !objectDelete(obj, name, throw) {
|
||||
return false
|
||||
}
|
||||
if _, exists := self.value.(_argumentsObject).get(name); exists {
|
||||
self.value.(_argumentsObject).delete(name)
|
||||
if _, exists := obj.value.(argumentsObject).get(name); exists {
|
||||
obj.value.(argumentsObject).delete(name)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
|
100
v1/vendor/github.com/robertkrimen/otto/type_array.go
generated
vendored
|
@ -4,43 +4,43 @@ import (
|
|||
"strconv"
|
||||
)
|
||||
|
||||
func (runtime *_runtime) newArrayObject(length uint32) *_object {
|
||||
self := runtime.newObject()
|
||||
self.class = classArray
|
||||
self.defineProperty(propertyLength, toValue_uint32(length), 0100, false)
|
||||
self.objectClass = _classArray
|
||||
return self
|
||||
func (rt *runtime) newArrayObject(length uint32) *object {
|
||||
obj := rt.newObject()
|
||||
obj.class = classArrayName
|
||||
obj.defineProperty(propertyLength, uint32Value(length), 0o100, false)
|
||||
obj.objectClass = classArray
|
||||
return obj
|
||||
}
|
||||
|
||||
func isArray(object *_object) bool {
|
||||
if object == nil {
|
||||
func isArray(obj *object) bool {
|
||||
if obj == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
switch object.class {
|
||||
case classArray, classGoArray, classGoSlice:
|
||||
switch obj.class {
|
||||
case classArrayName, classGoArrayName, classGoSliceName:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func objectLength(object *_object) uint32 {
|
||||
if object == nil {
|
||||
func objectLength(obj *object) uint32 {
|
||||
if obj == nil {
|
||||
return 0
|
||||
}
|
||||
switch object.class {
|
||||
case classArray:
|
||||
return object.get(propertyLength).value.(uint32)
|
||||
case classString:
|
||||
return uint32(object.get(propertyLength).value.(int))
|
||||
case classGoArray, classGoSlice:
|
||||
return uint32(object.get(propertyLength).value.(int))
|
||||
switch obj.class {
|
||||
case classArrayName:
|
||||
return obj.get(propertyLength).value.(uint32)
|
||||
case classStringName:
|
||||
return uint32(obj.get(propertyLength).value.(int))
|
||||
case classGoArrayName, classGoSliceName:
|
||||
return uint32(obj.get(propertyLength).value.(int))
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func arrayUint32(rt *_runtime, value Value) uint32 {
|
||||
func arrayUint32(rt *runtime, value Value) uint32 {
|
||||
nm := value.number()
|
||||
if nm.kind != numberInteger || !isUint32(nm.int64) {
|
||||
// FIXME
|
||||
|
@ -49,70 +49,72 @@ func arrayUint32(rt *_runtime, value Value) uint32 {
|
|||
return uint32(nm.int64)
|
||||
}
|
||||
|
||||
func arrayDefineOwnProperty(self *_object, name string, descriptor _property, throw bool) bool {
|
||||
lengthProperty := self.getOwnProperty(propertyLength)
|
||||
func arrayDefineOwnProperty(obj *object, name string, descriptor property, throw bool) bool {
|
||||
lengthProperty := obj.getOwnProperty(propertyLength)
|
||||
lengthValue, valid := lengthProperty.value.(Value)
|
||||
if !valid {
|
||||
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)
|
||||
if name == propertyLength {
|
||||
if descriptor.value == nil {
|
||||
return objectDefineOwnProperty(self, name, descriptor, throw)
|
||||
return objectDefineOwnProperty(obj, name, descriptor, throw)
|
||||
}
|
||||
newLengthValue, isValue := descriptor.value.(Value)
|
||||
if !isValue {
|
||||
panic(self.runtime.panicTypeError())
|
||||
panic(obj.runtime.panicTypeError("Array.DefineOwnProperty %q is not a value", descriptor.value))
|
||||
}
|
||||
newLength := arrayUint32(self.runtime, newLengthValue)
|
||||
descriptor.value = toValue_uint32(newLength)
|
||||
newLength := arrayUint32(obj.runtime, newLengthValue)
|
||||
descriptor.value = uint32Value(newLength)
|
||||
if newLength > length {
|
||||
return objectDefineOwnProperty(self, name, descriptor, throw)
|
||||
return objectDefineOwnProperty(obj, name, descriptor, throw)
|
||||
}
|
||||
if !lengthProperty.writable() {
|
||||
goto Reject
|
||||
return reject("property length for not writable")
|
||||
}
|
||||
newWritable := true
|
||||
if descriptor.mode&0700 == 0 {
|
||||
if descriptor.mode&0o700 == 0 {
|
||||
// If writable is off
|
||||
newWritable = false
|
||||
descriptor.mode |= 0100
|
||||
descriptor.mode |= 0o100
|
||||
}
|
||||
if !objectDefineOwnProperty(self, name, descriptor, throw) {
|
||||
if !objectDefineOwnProperty(obj, name, descriptor, throw) {
|
||||
return false
|
||||
}
|
||||
for newLength < length {
|
||||
length--
|
||||
if !self.delete(strconv.FormatInt(int64(length), 10), false) {
|
||||
descriptor.value = toValue_uint32(length + 1)
|
||||
if !obj.delete(strconv.FormatInt(int64(length), 10), false) {
|
||||
descriptor.value = uint32Value(length + 1)
|
||||
if !newWritable {
|
||||
descriptor.mode &= 0077
|
||||
descriptor.mode &= 0o077
|
||||
}
|
||||
objectDefineOwnProperty(self, name, descriptor, false)
|
||||
goto Reject
|
||||
objectDefineOwnProperty(obj, name, descriptor, false)
|
||||
return reject("delete failed")
|
||||
}
|
||||
}
|
||||
if !newWritable {
|
||||
descriptor.mode &= 0077
|
||||
objectDefineOwnProperty(self, name, descriptor, false)
|
||||
descriptor.mode &= 0o077
|
||||
objectDefineOwnProperty(obj, name, descriptor, false)
|
||||
}
|
||||
} else if index := stringToArrayIndex(name); index >= 0 {
|
||||
if index >= int64(length) && !lengthProperty.writable() {
|
||||
goto Reject
|
||||
return reject("property length not writable")
|
||||
}
|
||||
if !objectDefineOwnProperty(self, strconv.FormatInt(index, 10), descriptor, false) {
|
||||
goto Reject
|
||||
if !objectDefineOwnProperty(obj, strconv.FormatInt(index, 10), descriptor, false) {
|
||||
return reject("Object.DefineOwnProperty failed")
|
||||
}
|
||||
if index >= int64(length) {
|
||||
lengthProperty.value = toValue_uint32(uint32(index + 1))
|
||||
objectDefineOwnProperty(self, propertyLength, *lengthProperty, false)
|
||||
lengthProperty.value = uint32Value(uint32(index + 1))
|
||||
objectDefineOwnProperty(obj, propertyLength, *lengthProperty, false)
|
||||
return true
|
||||
}
|
||||
}
|
||||
return objectDefineOwnProperty(self, name, descriptor, throw)
|
||||
Reject:
|
||||
if throw {
|
||||
panic(self.runtime.panicTypeError())
|
||||
}
|
||||
return false
|
||||
return objectDefineOwnProperty(obj, name, descriptor, throw)
|
||||
}
|
||||
|
|
4
v1/vendor/github.com/robertkrimen/otto/type_boolean.go
generated
vendored
|
@ -1,5 +1,5 @@
|
|||
package otto
|
||||
|
||||
func (runtime *_runtime) newBooleanObject(value Value) *_object {
|
||||
return runtime.newPrimitiveObject(classBoolean, toValue_bool(value.bool()))
|
||||
func (rt *runtime) newBooleanObject(value Value) *object {
|
||||
return rt.newPrimitiveObject(classBooleanName, boolValue(value.bool()))
|
||||
}
|
||||
|
|
164
v1/vendor/github.com/robertkrimen/otto/type_date.go
generated
vendored
|
@ -7,23 +7,21 @@ import (
|
|||
Time "time"
|
||||
)
|
||||
|
||||
type _dateObject struct {
|
||||
type dateObject struct {
|
||||
time Time.Time // Time from the "time" package, a cached version of time
|
||||
epoch int64
|
||||
value Value
|
||||
isNaN bool
|
||||
}
|
||||
|
||||
var (
|
||||
invalidDateObject = _dateObject{
|
||||
var invalidDateObject = dateObject{
|
||||
time: Time.Time{},
|
||||
epoch: -1,
|
||||
value: NaNValue(),
|
||||
isNaN: true,
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
type _ecmaTime struct {
|
||||
type ecmaTime struct {
|
||||
year int
|
||||
month int
|
||||
day int
|
||||
|
@ -34,8 +32,8 @@ type _ecmaTime struct {
|
|||
location *Time.Location // Basically, either local or UTC
|
||||
}
|
||||
|
||||
func ecmaTime(goTime Time.Time) _ecmaTime {
|
||||
return _ecmaTime{
|
||||
func newEcmaTime(goTime Time.Time) ecmaTime {
|
||||
return ecmaTime{
|
||||
goTime.Year(),
|
||||
dateFromGoMonth(goTime.Month()),
|
||||
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(
|
||||
self.year,
|
||||
dateToGoMonth(self.month),
|
||||
self.day,
|
||||
self.hour,
|
||||
self.minute,
|
||||
self.second,
|
||||
self.millisecond*(100*100*100),
|
||||
self.location,
|
||||
t.year,
|
||||
dateToGoMonth(t.month),
|
||||
t.day,
|
||||
t.hour,
|
||||
t.minute,
|
||||
t.second,
|
||||
t.millisecond*(100*100*100),
|
||||
t.location,
|
||||
)
|
||||
}
|
||||
|
||||
func (self *_dateObject) Time() Time.Time {
|
||||
return self.time
|
||||
func (d *dateObject) Time() Time.Time {
|
||||
return d.time
|
||||
}
|
||||
|
||||
func (self *_dateObject) Epoch() int64 {
|
||||
return self.epoch
|
||||
func (d *dateObject) Epoch() int64 {
|
||||
return d.epoch
|
||||
}
|
||||
|
||||
func (self *_dateObject) Value() Value {
|
||||
return self.value
|
||||
func (d *dateObject) Value() 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
|
||||
func (self *_dateObject) SetNaN() {
|
||||
self.time = Time.Time{}
|
||||
self.epoch = -1
|
||||
self.value = NaNValue()
|
||||
self.isNaN = true
|
||||
// FIXME A date should only be in the range of -100,000,000 to +100,000,000 (1970): 15.9.1.1.
|
||||
func (d *dateObject) SetNaN() {
|
||||
d.time = Time.Time{}
|
||||
d.epoch = -1
|
||||
d.value = NaNValue()
|
||||
d.isNaN = true
|
||||
}
|
||||
|
||||
func (self *_dateObject) SetTime(time Time.Time) {
|
||||
self.Set(timeToEpoch(time))
|
||||
func (d *dateObject) SetTime(time Time.Time) {
|
||||
d.Set(timeToEpoch(time))
|
||||
}
|
||||
|
||||
func (self *_dateObject) Set(epoch float64) {
|
||||
func (d *dateObject) Set(epoch float64) {
|
||||
// epoch
|
||||
self.epoch = epochToInteger(epoch)
|
||||
d.epoch = epochToInteger(epoch)
|
||||
|
||||
// time
|
||||
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
|
||||
if err != nil {
|
||||
self.isNaN = true
|
||||
self.epoch = -1
|
||||
self.value = NaNValue()
|
||||
d.isNaN = true
|
||||
d.epoch = -1
|
||||
d.value = NaNValue()
|
||||
} 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))
|
||||
}
|
||||
|
||||
func epochToTime(value float64) (time Time.Time, err error) {
|
||||
func epochToTime(value float64) (Time.Time, error) {
|
||||
epochWithMilli := value
|
||||
if math.IsNaN(epochWithMilli) || math.IsInf(epochWithMilli, 0) {
|
||||
err = fmt.Errorf("Invalid time %v", value)
|
||||
return
|
||||
return Time.Time{}, fmt.Errorf("invalid time %v", value)
|
||||
}
|
||||
|
||||
epoch := int64(epochWithMilli / 1000)
|
||||
milli := int64(epochWithMilli) % 1000
|
||||
|
||||
time = Time.Unix(int64(epoch), milli*1000000).In(utcTimeZone)
|
||||
return
|
||||
return Time.Unix(epoch, milli*1000000).In(utcTimeZone), nil
|
||||
}
|
||||
|
||||
func timeToEpoch(time Time.Time) float64 {
|
||||
return float64(time.UnixMilli())
|
||||
}
|
||||
|
||||
func (runtime *_runtime) newDateObject(epoch float64) *_object {
|
||||
self := runtime.newObject()
|
||||
self.class = classDate
|
||||
func (rt *runtime) newDateObject(epoch float64) *object {
|
||||
obj := rt.newObject()
|
||||
obj.class = classDateName
|
||||
|
||||
// FIXME This is ugly...
|
||||
date := _dateObject{}
|
||||
date := dateObject{}
|
||||
date.Set(epoch)
|
||||
self.value = date
|
||||
return self
|
||||
obj.value = date
|
||||
return obj
|
||||
}
|
||||
|
||||
func (self *_object) dateValue() _dateObject {
|
||||
value, _ := self.value.(_dateObject)
|
||||
func (o *object) dateValue() dateObject {
|
||||
value, _ := o.value.(dateObject)
|
||||
return value
|
||||
}
|
||||
|
||||
func dateObjectOf(rt *_runtime, _dateObject *_object) _dateObject {
|
||||
if _dateObject == nil || _dateObject.class != classDate {
|
||||
panic(rt.panicTypeError())
|
||||
func dateObjectOf(rt *runtime, date *object) dateObject {
|
||||
if date == nil {
|
||||
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 {
|
||||
return Time.Month(month + 1)
|
||||
}
|
||||
|
@ -163,7 +162,8 @@ func dateFromGoDay(day Time.Weekday) int {
|
|||
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) {
|
||||
if index >= len(argumentList) {
|
||||
return default_, false
|
||||
|
@ -175,29 +175,41 @@ func newDateTime(argumentList []Value, location *Time.Location) (epoch float64)
|
|||
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 invalid bool
|
||||
if year, invalid = pick(0, 1900.0); invalid {
|
||||
goto INVALID
|
||||
return math.NaN()
|
||||
}
|
||||
if month, invalid = pick(1, 0.0); invalid {
|
||||
goto INVALID
|
||||
return math.NaN()
|
||||
}
|
||||
if day, invalid = pick(2, 1.0); invalid {
|
||||
goto INVALID
|
||||
return math.NaN()
|
||||
}
|
||||
if hour, invalid = pick(3, 0.0); invalid {
|
||||
goto INVALID
|
||||
return math.NaN()
|
||||
}
|
||||
if minute, invalid = pick(4, 0.0); invalid {
|
||||
goto INVALID
|
||||
return math.NaN()
|
||||
}
|
||||
if second, invalid = pick(5, 0.0); invalid {
|
||||
goto INVALID
|
||||
return math.NaN()
|
||||
}
|
||||
if millisecond, invalid = pick(6, 0.0); invalid {
|
||||
goto INVALID
|
||||
return math.NaN()
|
||||
}
|
||||
|
||||
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)
|
||||
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 (
|
||||
|
@ -238,6 +235,10 @@ var (
|
|||
"2006-01T15:04:05",
|
||||
"2006-01-02T15:04:05",
|
||||
|
||||
"2006/01",
|
||||
"2006/01/02",
|
||||
"2006/01/02 15:04:05",
|
||||
|
||||
"2006T15:04:05.000",
|
||||
"2006-01T15:04:05.000",
|
||||
"2006-01-02T15:04:05.000",
|
||||
|
@ -259,7 +260,8 @@ var (
|
|||
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
|
||||
var time Time.Time
|
||||
var err error
|
||||
|
|
54
v1/vendor/github.com/robertkrimen/otto/type_error.go
generated
vendored
|
@ -1,58 +1,58 @@
|
|||
package otto
|
||||
|
||||
func (rt *_runtime) newErrorObject(name string, message Value, stackFramesToPop int) *_object {
|
||||
self := rt.newClassObject(classError)
|
||||
func (rt *runtime) newErrorObject(name string, message Value, stackFramesToPop int) *object {
|
||||
obj := rt.newClassObject(classErrorName)
|
||||
if message.IsDefined() {
|
||||
msg := message.string()
|
||||
self.defineProperty("message", toValue_string(msg), 0111, false)
|
||||
self.value = newError(rt, name, stackFramesToPop, msg)
|
||||
err := newError(rt, name, stackFramesToPop, "%s", message.string())
|
||||
obj.defineProperty("message", err.messageValue(), 0o111, false)
|
||||
obj.value = err
|
||||
} else {
|
||||
self.value = newError(rt, name, stackFramesToPop)
|
||||
obj.value = newError(rt, name, stackFramesToPop)
|
||||
}
|
||||
|
||||
self.defineOwnProperty("stack", _property{
|
||||
value: _propertyGetSet{
|
||||
obj.defineOwnProperty("stack", property{
|
||||
value: propertyGetSet{
|
||||
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,
|
||||
}, false)
|
||||
|
||||
return self
|
||||
return obj
|
||||
}
|
||||
|
||||
func (rt *_runtime) newErrorObjectError(err _error) *_object {
|
||||
self := rt.newClassObject(classError)
|
||||
self.defineProperty("message", err.messageValue(), 0111, false)
|
||||
self.value = err
|
||||
func (rt *runtime) newErrorObjectError(err ottoError) *object {
|
||||
obj := rt.newClassObject(classErrorName)
|
||||
obj.defineProperty("message", err.messageValue(), 0o111, false)
|
||||
obj.value = err
|
||||
switch err.name {
|
||||
case "EvalError":
|
||||
self.prototype = rt.global.EvalErrorPrototype
|
||||
obj.prototype = rt.global.EvalErrorPrototype
|
||||
case "TypeError":
|
||||
self.prototype = rt.global.TypeErrorPrototype
|
||||
obj.prototype = rt.global.TypeErrorPrototype
|
||||
case "RangeError":
|
||||
self.prototype = rt.global.RangeErrorPrototype
|
||||
obj.prototype = rt.global.RangeErrorPrototype
|
||||
case "ReferenceError":
|
||||
self.prototype = rt.global.ReferenceErrorPrototype
|
||||
obj.prototype = rt.global.ReferenceErrorPrototype
|
||||
case "SyntaxError":
|
||||
self.prototype = rt.global.SyntaxErrorPrototype
|
||||
obj.prototype = rt.global.SyntaxErrorPrototype
|
||||
case "URIError":
|
||||
self.prototype = rt.global.URIErrorPrototype
|
||||
obj.prototype = rt.global.URIErrorPrototype
|
||||
default:
|
||||
self.prototype = rt.global.ErrorPrototype
|
||||
obj.prototype = rt.global.ErrorPrototype
|
||||
}
|
||||
|
||||
self.defineOwnProperty("stack", _property{
|
||||
value: _propertyGetSet{
|
||||
obj.defineOwnProperty("stack", property{
|
||||
value: propertyGetSet{
|
||||
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,
|
||||
}, false)
|
||||
|
||||
return self
|
||||
return obj
|
||||
}
|
||||
|
|
289
v1/vendor/github.com/robertkrimen/otto/type_function.go
generated
vendored
|
@ -1,20 +1,20 @@
|
|||
package otto
|
||||
|
||||
// _constructFunction
|
||||
type _constructFunction func(*_object, []Value) Value
|
||||
// constructFunction.
|
||||
type constructFunction func(*object, []Value) Value
|
||||
|
||||
// 13.2.2 [[Construct]]
|
||||
func defaultConstruct(fn *_object, argumentList []Value) Value {
|
||||
object := fn.runtime.newObject()
|
||||
object.class = classObject
|
||||
// 13.2.2 [[Construct]].
|
||||
func defaultConstruct(fn *object, argumentList []Value) Value {
|
||||
obj := fn.runtime.newObject()
|
||||
obj.class = classObjectName
|
||||
|
||||
prototype := fn.get("prototype")
|
||||
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)
|
||||
if value.kind == valueObject {
|
||||
return value
|
||||
|
@ -22,72 +22,66 @@ func defaultConstruct(fn *_object, argumentList []Value) Value {
|
|||
return this
|
||||
}
|
||||
|
||||
// _nativeFunction
|
||||
type _nativeFunction func(FunctionCall) Value
|
||||
// nativeFunction.
|
||||
type nativeFunction func(FunctionCall) Value
|
||||
|
||||
// ===================== //
|
||||
// _nativeFunctionObject //
|
||||
// ===================== //
|
||||
|
||||
type _nativeFunctionObject struct {
|
||||
// nativeFunctionObject.
|
||||
type nativeFunctionObject struct {
|
||||
name string
|
||||
file string
|
||||
line int
|
||||
call _nativeFunction // [[Call]]
|
||||
construct _constructFunction // [[Construct]]
|
||||
call nativeFunction // [[Call]]
|
||||
construct constructFunction // [[Construct]]
|
||||
}
|
||||
|
||||
func (runtime *_runtime) _newNativeFunctionObject(name, file string, line int, native _nativeFunction, length int) *_object {
|
||||
self := runtime.newClassObject(classFunction)
|
||||
self.value = _nativeFunctionObject{
|
||||
func (rt *runtime) newNativeFunctionProperty(name, file string, line int, native nativeFunction, length int) *object {
|
||||
o := rt.newClassObject(classFunctionName)
|
||||
o.value = nativeFunctionObject{
|
||||
name: name,
|
||||
file: file,
|
||||
line: line,
|
||||
call: native,
|
||||
construct: defaultConstruct,
|
||||
}
|
||||
self.defineProperty("name", toValue_string(name), 0000, false)
|
||||
self.defineProperty(propertyLength, toValue_int(length), 0000, false)
|
||||
return self
|
||||
o.defineProperty("name", stringValue(name), 0o000, false)
|
||||
o.defineProperty(propertyLength, intValue(length), 0o000, false)
|
||||
return o
|
||||
}
|
||||
|
||||
func (runtime *_runtime) newNativeFunctionObject(name, file string, line int, native _nativeFunction, length int) *_object {
|
||||
self := runtime._newNativeFunctionObject(name, file, line, native, length)
|
||||
self.defineOwnProperty("caller", _property{
|
||||
value: _propertyGetSet{
|
||||
runtime._newNativeFunctionObject("get", "internal", 0, func(fc FunctionCall) Value {
|
||||
for sc := runtime.scope; sc != nil; sc = sc.outer {
|
||||
if sc.frame.fn == self {
|
||||
func (rt *runtime) newNativeFunctionObject(name, file string, line int, native nativeFunction, length int) *object {
|
||||
o := rt.newNativeFunctionProperty(name, file, line, native, length)
|
||||
o.defineOwnProperty("caller", property{
|
||||
value: propertyGetSet{
|
||||
rt.newNativeFunctionProperty("get", "internal", 0, func(fc FunctionCall) Value {
|
||||
for sc := rt.scope; sc != nil; sc = sc.outer {
|
||||
if sc.frame.fn == o {
|
||||
if sc.outer == nil || sc.outer.frame.fn == nil {
|
||||
return nullValue
|
||||
}
|
||||
|
||||
return runtime.toValue(sc.outer.frame.fn)
|
||||
return rt.toValue(sc.outer.frame.fn)
|
||||
}
|
||||
}
|
||||
|
||||
return nullValue
|
||||
}, 0),
|
||||
&_nilGetSetObject,
|
||||
&nilGetSetObject,
|
||||
},
|
||||
mode: 0000,
|
||||
mode: 0o000,
|
||||
}, false)
|
||||
return self
|
||||
return o
|
||||
}
|
||||
|
||||
// =================== //
|
||||
// _bindFunctionObject //
|
||||
// =================== //
|
||||
|
||||
type _bindFunctionObject struct {
|
||||
target *_object
|
||||
// bindFunctionObject.
|
||||
type bindFunctionObject struct {
|
||||
target *object
|
||||
this Value
|
||||
argumentList []Value
|
||||
}
|
||||
|
||||
func (runtime *_runtime) newBoundFunctionObject(target *_object, this Value, argumentList []Value) *_object {
|
||||
self := runtime.newClassObject(classFunction)
|
||||
self.value = _bindFunctionObject{
|
||||
func (rt *runtime) newBoundFunctionObject(target *object, this Value, argumentList []Value) *object {
|
||||
o := rt.newClassObject(classFunctionName)
|
||||
o.value = bindFunctionObject{
|
||||
target: target,
|
||||
this: this,
|
||||
argumentList: argumentList,
|
||||
|
@ -97,100 +91,96 @@ func (runtime *_runtime) newBoundFunctionObject(target *_object, this Value, arg
|
|||
if length < 0 {
|
||||
length = 0
|
||||
}
|
||||
self.defineProperty("name", toValue_string("bound "+target.get("name").String()), 0000, false)
|
||||
self.defineProperty(propertyLength, toValue_int(length), 0000, false)
|
||||
self.defineProperty("caller", Value{}, 0000, false) // TODO Should throw a TypeError
|
||||
self.defineProperty("arguments", Value{}, 0000, false) // TODO Should throw a TypeError
|
||||
return self
|
||||
o.defineProperty("name", stringValue("bound "+target.get("name").String()), 0o000, false)
|
||||
o.defineProperty(propertyLength, intValue(length), 0o000, false)
|
||||
o.defineProperty("caller", Value{}, 0o000, false) // TODO Should throw a TypeError
|
||||
o.defineProperty("arguments", Value{}, 0o000, false) // TODO Should throw a TypeError
|
||||
return o
|
||||
}
|
||||
|
||||
// [[Construct]]
|
||||
func (fn _bindFunctionObject) construct(argumentList []Value) Value {
|
||||
object := fn.target
|
||||
switch value := object.value.(type) {
|
||||
case _nativeFunctionObject:
|
||||
return value.construct(object, fn.argumentList)
|
||||
case _nodeFunctionObject:
|
||||
// [[Construct]].
|
||||
func (fn bindFunctionObject) construct(argumentList []Value) Value {
|
||||
obj := fn.target
|
||||
switch value := obj.value.(type) {
|
||||
case nativeFunctionObject:
|
||||
return value.construct(obj, fn.argumentList)
|
||||
case nodeFunctionObject:
|
||||
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 //
|
||||
// =================== //
|
||||
|
||||
type _nodeFunctionObject struct {
|
||||
node *_nodeFunctionLiteral
|
||||
stash _stash
|
||||
// nodeFunctionObject.
|
||||
type nodeFunctionObject struct {
|
||||
node *nodeFunctionLiteral
|
||||
stash stasher
|
||||
}
|
||||
|
||||
func (runtime *_runtime) newNodeFunctionObject(node *_nodeFunctionLiteral, stash _stash) *_object {
|
||||
self := runtime.newClassObject(classFunction)
|
||||
self.value = _nodeFunctionObject{
|
||||
func (rt *runtime) newNodeFunctionObject(node *nodeFunctionLiteral, stash stasher) *object {
|
||||
o := rt.newClassObject(classFunctionName)
|
||||
o.value = nodeFunctionObject{
|
||||
node: node,
|
||||
stash: stash,
|
||||
}
|
||||
self.defineProperty("name", toValue_string(node.name), 0000, false)
|
||||
self.defineProperty(propertyLength, toValue_int(len(node.parameterList)), 0000, false)
|
||||
self.defineOwnProperty("caller", _property{
|
||||
value: _propertyGetSet{
|
||||
runtime.newNativeFunction("get", "internal", 0, func(fc FunctionCall) Value {
|
||||
for sc := runtime.scope; sc != nil; sc = sc.outer {
|
||||
if sc.frame.fn == self {
|
||||
o.defineProperty("name", stringValue(node.name), 0o000, false)
|
||||
o.defineProperty(propertyLength, intValue(len(node.parameterList)), 0o000, false)
|
||||
o.defineOwnProperty("caller", property{
|
||||
value: propertyGetSet{
|
||||
rt.newNativeFunction("get", "internal", 0, func(fc FunctionCall) Value {
|
||||
for sc := rt.scope; sc != nil; sc = sc.outer {
|
||||
if sc.frame.fn == o {
|
||||
if sc.outer == nil || sc.outer.frame.fn == nil {
|
||||
return nullValue
|
||||
}
|
||||
|
||||
return runtime.toValue(sc.outer.frame.fn)
|
||||
return rt.toValue(sc.outer.frame.fn)
|
||||
}
|
||||
}
|
||||
|
||||
return nullValue
|
||||
}),
|
||||
&_nilGetSetObject,
|
||||
&nilGetSetObject,
|
||||
},
|
||||
mode: 0000,
|
||||
mode: 0o000,
|
||||
}, false)
|
||||
return self
|
||||
return o
|
||||
}
|
||||
|
||||
// ======= //
|
||||
// _object //
|
||||
// ======= //
|
||||
|
||||
func (self *_object) isCall() bool {
|
||||
switch fn := self.value.(type) {
|
||||
case _nativeFunctionObject:
|
||||
// _object.
|
||||
func (o *object) isCall() bool {
|
||||
switch fn := o.value.(type) {
|
||||
case nativeFunctionObject:
|
||||
return fn.call != nil
|
||||
case _bindFunctionObject:
|
||||
case bindFunctionObject:
|
||||
return true
|
||||
case _nodeFunctionObject:
|
||||
case nodeFunctionObject:
|
||||
return true
|
||||
}
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func (self *_object) call(this Value, argumentList []Value, eval bool, frame _frame) Value {
|
||||
switch fn := self.value.(type) {
|
||||
case _nativeFunctionObject:
|
||||
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 := o.value.(type) {
|
||||
case nativeFunctionObject:
|
||||
// Since eval is a native function, we only have to check for it here
|
||||
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...
|
||||
rt := self.runtime
|
||||
rt := o.runtime
|
||||
if rt.scope != nil && !eval {
|
||||
rt.enterFunctionScope(rt.scope.lexical, this)
|
||||
rt.scope.frame = _frame{
|
||||
rt.scope.frame = frame{
|
||||
native: true,
|
||||
nativeFile: fn.file,
|
||||
nativeLine: fn.line,
|
||||
callee: fn.name,
|
||||
file: nil,
|
||||
fn: self,
|
||||
fn: o,
|
||||
}
|
||||
defer func() {
|
||||
rt.leaveScope()
|
||||
|
@ -198,77 +188,77 @@ func (self *_object) call(this Value, argumentList []Value, eval bool, frame _fr
|
|||
}
|
||||
|
||||
return fn.call(FunctionCall{
|
||||
runtime: self.runtime,
|
||||
runtime: o.runtime,
|
||||
eval: eval,
|
||||
|
||||
This: this,
|
||||
ArgumentList: argumentList,
|
||||
Otto: self.runtime.otto,
|
||||
Otto: o.runtime.otto,
|
||||
})
|
||||
|
||||
case _bindFunctionObject:
|
||||
case bindFunctionObject:
|
||||
// TODO Passthrough site, do not enter a scope
|
||||
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:
|
||||
rt := self.runtime
|
||||
case nodeFunctionObject:
|
||||
rt := o.runtime
|
||||
stash := rt.enterFunctionScope(fn.stash, this)
|
||||
rt.scope.frame = _frame{
|
||||
rt.scope.frame = frame{
|
||||
callee: fn.node.name,
|
||||
file: fn.node.file,
|
||||
fn: self,
|
||||
fn: o,
|
||||
}
|
||||
defer func() {
|
||||
rt.leaveScope()
|
||||
}()
|
||||
callValue := rt.cmpl_call_nodeFunction(self, stash, fn.node, this, argumentList)
|
||||
if value, valid := callValue.value.(_result); valid {
|
||||
callValue := rt.cmplCallNodeFunction(o, stash, fn.node, argumentList)
|
||||
if value, valid := callValue.value.(result); valid {
|
||||
return value.value
|
||||
}
|
||||
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 {
|
||||
switch fn := self.value.(type) {
|
||||
case _nativeFunctionObject:
|
||||
func (o *object) construct(argumentList []Value) Value {
|
||||
switch fn := o.value.(type) {
|
||||
case nativeFunctionObject:
|
||||
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 {
|
||||
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)
|
||||
|
||||
case _nodeFunctionObject:
|
||||
return defaultConstruct(self, argumentList)
|
||||
case nodeFunctionObject:
|
||||
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
|
||||
func (self *_object) hasInstance(of Value) bool {
|
||||
if !self.isCall() {
|
||||
// 15.3.5.3.
|
||||
func (o *object) hasInstance(of Value) bool {
|
||||
if !o.isCall() {
|
||||
// We should not have a hasInstance method
|
||||
panic(self.runtime.panicTypeError())
|
||||
panic(o.runtime.panicTypeError("Object.hasInstance not callable"))
|
||||
}
|
||||
if !of.IsObject() {
|
||||
return false
|
||||
}
|
||||
prototype := self.get("prototype")
|
||||
prototype := o.get("prototype")
|
||||
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 {
|
||||
if value == prototypeObject {
|
||||
return true
|
||||
|
@ -278,14 +268,10 @@ func (self *_object) hasInstance(of Value) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
// ============ //
|
||||
// FunctionCall //
|
||||
// ============ //
|
||||
|
||||
// FunctionCall is an encapsulation of a JavaScript function call.
|
||||
type FunctionCall struct {
|
||||
runtime *_runtime
|
||||
_thisObject *_object
|
||||
runtime *runtime
|
||||
thisObj *object
|
||||
eval bool // This call is a direct call to eval
|
||||
|
||||
This Value
|
||||
|
@ -296,43 +282,42 @@ type FunctionCall struct {
|
|||
// Argument will return the value of the argument at the given index.
|
||||
//
|
||||
// If no such argument exists, undefined is returned.
|
||||
func (self FunctionCall) Argument(index int) Value {
|
||||
return valueOfArrayIndex(self.ArgumentList, index)
|
||||
func (f FunctionCall) Argument(index int) Value {
|
||||
return valueOfArrayIndex(f.ArgumentList, index)
|
||||
}
|
||||
|
||||
func (self FunctionCall) getArgument(index int) (Value, bool) {
|
||||
return getValueOfArrayIndex(self.ArgumentList, index)
|
||||
func (f FunctionCall) getArgument(index int) (Value, bool) {
|
||||
return getValueOfArrayIndex(f.ArgumentList, index)
|
||||
}
|
||||
|
||||
func (self FunctionCall) slice(index int) []Value {
|
||||
if index < len(self.ArgumentList) {
|
||||
return self.ArgumentList[index:]
|
||||
func (f FunctionCall) slice(index int) []Value {
|
||||
if index < len(f.ArgumentList) {
|
||||
return f.ArgumentList[index:]
|
||||
}
|
||||
return []Value{}
|
||||
}
|
||||
|
||||
func (self *FunctionCall) thisObject() *_object {
|
||||
if self._thisObject == nil {
|
||||
this := self.This.resolve() // FIXME Is this right?
|
||||
self._thisObject = self.runtime.toObject(this)
|
||||
func (f *FunctionCall) thisObject() *object {
|
||||
if f.thisObj == nil {
|
||||
this := f.This.resolve() // FIXME Is this right?
|
||||
f.thisObj = f.runtime.toObject(this)
|
||||
}
|
||||
return self._thisObject
|
||||
return f.thisObj
|
||||
}
|
||||
|
||||
func (self *FunctionCall) thisClassObject(class string) *_object {
|
||||
thisObject := self.thisObject()
|
||||
if thisObject.class != class {
|
||||
panic(self.runtime.panicTypeError())
|
||||
func (f *FunctionCall) thisClassObject(class string) *object {
|
||||
if o := f.thisObject(); o.class != class {
|
||||
panic(f.runtime.panicTypeError("Function.Class %s != %s", o.class, class))
|
||||
}
|
||||
return self._thisObject
|
||||
return f.thisObj
|
||||
}
|
||||
|
||||
func (self FunctionCall) toObject(value Value) *_object {
|
||||
return self.runtime.toObject(value)
|
||||
func (f FunctionCall) toObject(value Value) *object {
|
||||
return f.runtime.toObject(value)
|
||||
}
|
||||
|
||||
// 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()
|
||||
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"
|
||||
)
|
||||
|
||||
func (runtime *_runtime) newGoArrayObject(value reflect.Value) *_object {
|
||||
self := runtime.newObject()
|
||||
self.class = classGoArray
|
||||
self.objectClass = _classGoArray
|
||||
self.value = _newGoArrayObject(value)
|
||||
return self
|
||||
func (rt *runtime) newGoArrayObject(value reflect.Value) *object {
|
||||
o := rt.newObject()
|
||||
o.class = classGoArrayName
|
||||
o.objectClass = classGoArray
|
||||
o.value = newGoArrayObject(value)
|
||||
return o
|
||||
}
|
||||
|
||||
type _goArrayObject struct {
|
||||
type goArrayObject struct {
|
||||
value reflect.Value
|
||||
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)
|
||||
mode := _propertyMode(0010)
|
||||
mode := propertyMode(0o010)
|
||||
if writable {
|
||||
mode = 0110
|
||||
mode = 0o110
|
||||
}
|
||||
self := &_goArrayObject{
|
||||
|
||||
return &goArrayObject{
|
||||
value: value,
|
||||
writable: writable,
|
||||
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 {
|
||||
v, ok := self.getValueIndex(index)
|
||||
v, ok := o.getValueIndex(index)
|
||||
if 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 reflect.Value{}, false
|
||||
}
|
||||
|
||||
func (self _goArrayObject) getValueIndex(index int64) (reflect.Value, bool) {
|
||||
value := reflect.Indirect(self.value)
|
||||
func (o goArrayObject) getValueIndex(index int64) (reflect.Value, bool) {
|
||||
value := reflect.Indirect(o.value)
|
||||
if index < int64(value.Len()) {
|
||||
return value.Index(int(index)), true
|
||||
}
|
||||
|
@ -57,12 +57,12 @@ func (self _goArrayObject) getValueIndex(index int64) (reflect.Value, bool) {
|
|||
return reflect.Value{}, false
|
||||
}
|
||||
|
||||
func (self _goArrayObject) setValue(index int64, value Value) bool {
|
||||
indexValue, exists := self.getValueIndex(index)
|
||||
func (o goArrayObject) setValue(index int64, value Value) bool {
|
||||
indexValue, exists := o.getValueIndex(index)
|
||||
if !exists {
|
||||
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 {
|
||||
panic(err)
|
||||
}
|
||||
|
@ -70,87 +70,87 @@ func (self _goArrayObject) setValue(index int64, value Value) bool {
|
|||
return true
|
||||
}
|
||||
|
||||
func goArrayGetOwnProperty(self *_object, name string) *_property {
|
||||
func goArrayGetOwnProperty(obj *object, name string) *property {
|
||||
// length
|
||||
if name == propertyLength {
|
||||
return &_property{
|
||||
value: toValue(reflect.Indirect(self.value.(*_goArrayObject).value).Len()),
|
||||
return &property{
|
||||
value: toValue(reflect.Indirect(obj.value.(*goArrayObject).value).Len()),
|
||||
mode: 0,
|
||||
}
|
||||
}
|
||||
|
||||
// .0, .1, .2, ...
|
||||
if index := stringToArrayIndex(name); index >= 0 {
|
||||
object := self.value.(*_goArrayObject)
|
||||
goObj := obj.value.(*goArrayObject)
|
||||
value := Value{}
|
||||
reflectValue, exists := object.getValueIndex(index)
|
||||
reflectValue, exists := goObj.getValueIndex(index)
|
||||
if exists {
|
||||
value = self.runtime.toValue(reflectValue.Interface())
|
||||
value = obj.runtime.toValue(reflectValue.Interface())
|
||||
}
|
||||
return &_property{
|
||||
return &property{
|
||||
value: value,
|
||||
mode: object.propertyMode,
|
||||
mode: goObj.propertyMode,
|
||||
}
|
||||
}
|
||||
|
||||
if method := self.value.(*_goArrayObject).value.MethodByName(name); method != (reflect.Value{}) {
|
||||
return &_property{
|
||||
self.runtime.toValue(method.Interface()),
|
||||
0110,
|
||||
if method := obj.value.(*goArrayObject).value.MethodByName(name); method != (reflect.Value{}) {
|
||||
return &property{
|
||||
obj.runtime.toValue(method.Interface()),
|
||||
0o110,
|
||||
}
|
||||
}
|
||||
|
||||
return objectGetOwnProperty(self, name)
|
||||
return objectGetOwnProperty(obj, name)
|
||||
}
|
||||
|
||||
func goArrayEnumerate(self *_object, all bool, each func(string) bool) {
|
||||
object := self.value.(*_goArrayObject)
|
||||
func goArrayEnumerate(obj *object, all bool, each func(string) bool) {
|
||||
goObj := obj.value.(*goArrayObject)
|
||||
// .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)
|
||||
if !each(name) {
|
||||
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 {
|
||||
return self.runtime.typeErrorResult(throw)
|
||||
return obj.runtime.typeErrorResult(throw)
|
||||
} else if index := stringToArrayIndex(name); index >= 0 {
|
||||
object := self.value.(*_goArrayObject)
|
||||
if object.writable {
|
||||
if self.value.(*_goArrayObject).setValue(index, descriptor.value.(Value)) {
|
||||
goObj := obj.value.(*goArrayObject)
|
||||
if goObj.writable {
|
||||
if obj.value.(*goArrayObject).setValue(index, descriptor.value.(Value)) {
|
||||
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
|
||||
if name == propertyLength {
|
||||
return self.runtime.typeErrorResult(throw)
|
||||
return obj.runtime.typeErrorResult(throw)
|
||||
}
|
||||
|
||||
// .0, .1, .2, ...
|
||||
index := stringToArrayIndex(name)
|
||||
if index >= 0 {
|
||||
object := self.value.(*_goArrayObject)
|
||||
if object.writable {
|
||||
indexValue, exists := object.getValueIndex(index)
|
||||
goObj := obj.value.(*goArrayObject)
|
||||
if goObj.writable {
|
||||
indexValue, exists := goObj.getValueIndex(index)
|
||||
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 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"
|
||||
)
|
||||
|
||||
func (runtime *_runtime) newGoMapObject(value reflect.Value) *_object {
|
||||
self := runtime.newObject()
|
||||
self.class = classObject // TODO Should this be something else?
|
||||
self.objectClass = _classGoMap
|
||||
self.value = _newGoMapObject(value)
|
||||
return self
|
||||
func (rt *runtime) newGoMapObject(value reflect.Value) *object {
|
||||
obj := rt.newObject()
|
||||
obj.class = classObjectName // TODO Should this be something else?
|
||||
obj.objectClass = classGoMap
|
||||
obj.value = newGoMapObject(value)
|
||||
return obj
|
||||
}
|
||||
|
||||
type _goMapObject struct {
|
||||
type goMapObject struct {
|
||||
value reflect.Value
|
||||
keyType reflect.Type
|
||||
valueType reflect.Type
|
||||
}
|
||||
|
||||
func _newGoMapObject(value reflect.Value) *_goMapObject {
|
||||
func newGoMapObject(value reflect.Value) *goMapObject {
|
||||
if value.Kind() != reflect.Map {
|
||||
dbgf("%/panic//%@: %v != reflect.Map", value.Kind())
|
||||
}
|
||||
self := &_goMapObject{
|
||||
return &goMapObject{
|
||||
value: value,
|
||||
keyType: value.Type().Key(),
|
||||
valueType: value.Type().Elem(),
|
||||
}
|
||||
return self
|
||||
}
|
||||
|
||||
func (self _goMapObject) toKey(name string) reflect.Value {
|
||||
reflectValue, err := stringToReflectValue(name, self.keyType.Kind())
|
||||
func (o goMapObject) toKey(name string) reflect.Value {
|
||||
reflectValue, err := stringToReflectValue(name, o.keyType.Kind())
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return reflectValue
|
||||
}
|
||||
|
||||
func (self _goMapObject) toValue(value Value) reflect.Value {
|
||||
reflectValue, err := value.toReflectValue(self.valueType)
|
||||
func (o goMapObject) toValue(value Value) reflect.Value {
|
||||
reflectValue, err := value.toReflectValue(o.valueType)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return reflectValue
|
||||
}
|
||||
|
||||
func goMapGetOwnProperty(self *_object, name string) *_property {
|
||||
object := self.value.(*_goMapObject)
|
||||
value := object.value.MapIndex(object.toKey(name))
|
||||
func goMapGetOwnProperty(obj *object, name string) *property {
|
||||
goObj := obj.value.(*goMapObject)
|
||||
|
||||
// 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() {
|
||||
return &_property{self.runtime.toValue(value.Interface()), 0111}
|
||||
return &property{obj.runtime.toValue(value.Interface()), 0o111}
|
||||
}
|
||||
|
||||
// Other methods
|
||||
if method := self.value.(*_goMapObject).value.MethodByName(name); method.IsValid() {
|
||||
return &_property{
|
||||
value: self.runtime.toValue(method.Interface()),
|
||||
mode: 0110,
|
||||
if method := obj.value.(*goMapObject).value.MethodByName(name); method.IsValid() {
|
||||
return &property{
|
||||
value: obj.runtime.toValue(method.Interface()),
|
||||
mode: 0o110,
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func goMapEnumerate(self *_object, all bool, each func(string) bool) {
|
||||
object := self.value.(*_goMapObject)
|
||||
keys := object.value.MapKeys()
|
||||
func goMapEnumerate(obj *object, all bool, each func(string) bool) {
|
||||
goObj := obj.value.(*goMapObject)
|
||||
keys := goObj.value.MapKeys()
|
||||
for _, key := range keys {
|
||||
if !each(toValue(key).String()) {
|
||||
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 {
|
||||
object := self.value.(*_goMapObject)
|
||||
func goMapDefineOwnProperty(obj *object, name string, descriptor property, throw bool) bool {
|
||||
goObj := obj.value.(*goMapObject)
|
||||
// TODO ...or 0222
|
||||
if descriptor.mode != 0111 {
|
||||
return self.runtime.typeErrorResult(throw)
|
||||
if descriptor.mode != 0o111 {
|
||||
return obj.runtime.typeErrorResult(throw)
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
func goMapDelete(self *_object, name string, throw bool) bool {
|
||||
object := self.value.(*_goMapObject)
|
||||
object.value.SetMapIndex(object.toKey(name), reflect.Value{})
|
||||
func goMapDelete(obj *object, name string, throw bool) bool {
|
||||
goObj := obj.value.(*goMapObject)
|
||||
goObj.value.SetMapIndex(goObj.toKey(name), reflect.Value{})
|
||||
// FIXME
|
||||
return true
|
||||
}
|
||||
|
|