aboutsummaryrefslogtreecommitdiffstats
path: root/Godeps/_workspace/src/github.com/robertkrimen/otto/otto.go
diff options
context:
space:
mode:
Diffstat (limited to 'Godeps/_workspace/src/github.com/robertkrimen/otto/otto.go')
-rw-r--r--Godeps/_workspace/src/github.com/robertkrimen/otto/otto.go91
1 files changed, 91 insertions, 0 deletions
diff --git a/Godeps/_workspace/src/github.com/robertkrimen/otto/otto.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/otto.go
index 9de3e08c5..2ec033cbc 100644
--- a/Godeps/_workspace/src/github.com/robertkrimen/otto/otto.go
+++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/otto.go
@@ -296,6 +296,24 @@ func (self Otto) Run(src interface{}) (Value, error) {
return value, err
}
+// Eval will do the same thing as Run, except without leaving the current scope.
+//
+// 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()
+ }
+
+ value, err := self.runtime.cmpl_eval(src)
+ if !value.safe() {
+ value = Value{}
+ }
+ return value, err
+}
+
// Get the value of the top-level binding of the given name.
//
// If there is an error (like the binding does not exist), then the value
@@ -341,6 +359,79 @@ func (self Otto) setValue(name string, value Value) {
self.runtime.globalStash.setValue(name, value, false)
}
+func (self Otto) SetDebuggerHandler(fn func(vm *Otto)) {
+ self.runtime.debugger = fn
+}
+
+// Context is a structure that contains information about the current execution
+// context.
+type Context struct {
+ Filename string
+ Line int
+ Column int
+ Callee string
+ Symbols map[string]Value
+ This Value
+ Stacktrace []string
+}
+
+// Context returns the current execution context of the vm
+func (self Otto) Context() (ctx Context) {
+ // Ensure we are operating in a scope
+ if self.runtime.scope == nil {
+ self.runtime.enterGlobalScope()
+ defer self.runtime.leaveScope()
+ }
+
+ scope := self.runtime.scope
+ frame := scope.frame
+
+ // Get location information
+ ctx.Filename = "<unknown>"
+ ctx.Callee = frame.callee
+ if frame.file != nil {
+ ctx.Filename = frame.file.Name()
+ if ctx.Filename == "" {
+ ctx.Filename = "<anonymous>"
+ }
+ ctx.Line, ctx.Column = _position(frame.file, frame.offset)
+ }
+
+ // Get the current scope this Value
+ ctx.This = toValue_object(scope.this)
+
+ // Build stacktrace (up to 10 levels deep)
+ limit := 10
+ ctx.Symbols = make(map[string]Value)
+ ctx.Stacktrace = append(ctx.Stacktrace, frame.location())
+ for limit > 0 {
+ // Get variables
+ stash := scope.lexical
+ for {
+ for _, name := range getStashProperties(stash) {
+ if _, ok := ctx.Symbols[name]; !ok {
+ ctx.Symbols[name] = stash.getBinding(name, true)
+ }
+ }
+ stash = stash.outer()
+ if stash == nil || stash.outer() == nil {
+ break
+ }
+ }
+
+ scope = scope.outer
+ if scope == nil {
+ break
+ }
+ if scope.frame.offset >= 0 {
+ ctx.Stacktrace = append(ctx.Stacktrace, scope.frame.location())
+ }
+ limit--
+ }
+
+ return
+}
+
// Call the given JavaScript with a given this and arguments.
//
// If this is nil, then some special handling takes place to determine the proper