aboutsummaryrefslogblamecommitdiffstats
path: root/vendor/github.com/robertkrimen/otto/global.go
blob: eb2a2a0fbfb598f4bda06b211d1a01c44c0dbf26 (plain) (tree)
1
2
3
4
5
6
7
8
9








                                                 



                                                       



                                               

                                    

                                     

                                   





                                             

                                           















                                             

                                                        


                         

                                                                                     






































                                                                                 
                                                       




                                                           
                                                      















                                                                                            
                                                       




                                                           
                                                        




                                                          
                                                       








                                                                                        
                                                                                                                      





                                              
                                                       

                                           
                                                   







                                                                            
                                                       





                                                                   
                                                     


                   
                                                                                              















                                                         
                                                                      
                                                      





                                                                              

                                                                                                                   
                                                         





                                                                                  
                                                                                                        

                                                                     
                                                         




                                                                                  









                                                                                                       
package otto

import (
    "strconv"
    "time"
)

var (
    prototypeValueObject   = interface{}(nil)
    prototypeValueFunction = _nativeFunctionObject{
        call: func(_ FunctionCall) Value {
            return Value{}
        },
    }
    prototypeValueString = _stringASCII("")
    // TODO Make this just false?
    prototypeValueBoolean = Value{
        kind:  valueBoolean,
        value: false,
    }
    prototypeValueNumber = Value{
        kind:  valueNumber,
        value: 0,
    }
    prototypeValueDate = _dateObject{
        epoch: 0,
        isNaN: false,
        time:  time.Unix(0, 0).UTC(),
        value: Value{
            kind:  valueNumber,
            value: 0,
        },
    }
    prototypeValueRegExp = _regExpObject{
        regularExpression: nil,
        global:            false,
        ignoreCase:        false,
        multiline:         false,
        source:            "",
        flags:             "",
    }
)

func newContext() *_runtime {

    self := &_runtime{}

    self.globalStash = self.newObjectStash(nil, nil)
    self.globalObject = self.globalStash.object

    _newContext(self)

    self.eval = self.globalObject.property["eval"].value.(Value).value.(*_object)
    self.globalObject.prototype = self.global.ObjectPrototype

    return self
}

func (runtime *_runtime) newBaseObject() *_object {
    self := newObject(runtime, "")
    return self
}

func (runtime *_runtime) newClassObject(class string) *_object {
    return newObject(runtime, class)
}

func (runtime *_runtime) newPrimitiveObject(class string, value Value) *_object {
    self := runtime.newClassObject(class)
    self.value = value
    return self
}

func (self *_object) primitiveValue() Value {
    switch value := self.value.(type) {
    case Value:
        return value
    case _stringObject:
        return toValue_string(value.String())
    }
    return Value{}
}

func (self *_object) hasPrimitive() bool {
    switch self.value.(type) {
    case Value, _stringObject:
        return true
    }
    return false
}

func (runtime *_runtime) newObject() *_object {
    self := runtime.newClassObject("Object")
    self.prototype = runtime.global.ObjectPrototype
    return self
}

func (runtime *_runtime) newArray(length uint32) *_object {
    self := runtime.newArrayObject(length)
    self.prototype = runtime.global.ArrayPrototype
    return self
}

func (runtime *_runtime) newArrayOf(valueArray []Value) *_object {
    self := runtime.newArray(uint32(len(valueArray)))
    for index, value := range valueArray {
        if value.isEmpty() {
            continue
        }
        self.defineProperty(strconv.FormatInt(int64(index), 10), value, 0111, false)
    }
    return self
}

func (runtime *_runtime) newString(value Value) *_object {
    self := runtime.newStringObject(value)
    self.prototype = runtime.global.StringPrototype
    return self
}

func (runtime *_runtime) newBoolean(value Value) *_object {
    self := runtime.newBooleanObject(value)
    self.prototype = runtime.global.BooleanPrototype
    return self
}

func (runtime *_runtime) newNumber(value Value) *_object {
    self := runtime.newNumberObject(value)
    self.prototype = runtime.global.NumberPrototype
    return self
}

func (runtime *_runtime) newRegExp(patternValue Value, flagsValue Value) *_object {

    pattern := ""
    flags := ""
    if object := patternValue._object(); object != nil && object.class == "RegExp" {
        if flagsValue.IsDefined() {
            panic(runtime.panicTypeError("Cannot supply flags when constructing one RegExp from another"))
        }
        regExp := object.regExpValue()
        pattern = regExp.source
        flags = regExp.flags
    } else {
        if patternValue.IsDefined() {
            pattern = patternValue.string()
        }
        if flagsValue.IsDefined() {
            flags = flagsValue.string()
        }
    }

    return runtime._newRegExp(pattern, flags)
}

func (runtime *_runtime) _newRegExp(pattern string, flags string) *_object {
    self := runtime.newRegExpObject(pattern, flags)
    self.prototype = runtime.global.RegExpPrototype
    return self
}

// 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
}

func (runtime *_runtime) newError(name string, message Value, stackFramesToPop int) *_object {
    var self *_object
    switch name {
    case "EvalError":
        return runtime.newEvalError(message)
    case "TypeError":
        return runtime.newTypeError(message)
    case "RangeError":
        return runtime.newRangeError(message)
    case "ReferenceError":
        return runtime.newReferenceError(message)
    case "SyntaxError":
        return runtime.newSyntaxError(message)
    case "URIError":
        return runtime.newURIError(message)
    }

    self = runtime.newErrorObject(name, message, stackFramesToPop)
    self.prototype = runtime.global.ErrorPrototype
    if name != "" {
        self.defineProperty("name", toValue_string(name), 0111, false)
    }
    return self
}

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 (runtime *_runtime) newNodeFunction(node *_nodeFunctionLiteral, scopeEnvironment _stash) *_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
}

// 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
}