sub eval_in_page { my ($self,$str,$env,$doc,$window) = @_; $env ||= {}; my $js_env = {}; $doc ||= $self->document; # do a manual transfer of keys, to circumvent our stupid # transformation routine: if (keys %$env) { $js_env = $self->repl->declare(<<'JS')->(); function () { return new Object } JS for my $k (keys %$env) { $js_env->{$k} = $env->{$k}; }; }; my $eval_in_sandbox = $self->repl->declare(<<'JS', 'list'); function (w,d,str,env,caller,line) { var unsafeWin = w.wrappedJSObject; var safeWin = XPCNativeWrapper(unsafeWin); var sandbox = Components.utils.Sandbox(safeWin); sandbox.window = safeWin; sandbox.document = d; // Transfer the environment for (var e in env) { sandbox[e] = env[e] sandbox.window[e] = env[e] } sandbox.__proto__ = unsafeWin; var res = Components.utils.evalInSandbox(str, sandbox, "1.8",caller,line); return [res,typeof(res)]; }; JS $window ||= $self->tab->{linkedBrowser}->{contentWindow}; # Report errors from scope of caller # This feels weirdly backwards here, but oh well: #local @CARP_NOT = (ref $self->repl); # we trust this my ($caller,$line) = (caller)[1,2]; $eval_in_sandbox->($window,$doc,$str,$js_env,$caller,$line); };