【问题标题】:ExecJS: keeping the context between two callsExecJS:保持两个调用之间的上下文
【发布时间】:2026-01-17 23:10:01
【问题描述】:

我目前正在尝试使用 ExecJS 为我正在开发的产品之一运行 Handlebars(注意:我知道 handlebars.rb gem 真的很酷,我使用了一段时间,但有一些问题要得到它安装在 Windows 上,所以我尝试了另一种自制的解决方案。

我遇到的一个问题是 Javascript 上下文没有保留在对 ExecJS 的每个“调用”之间。

这里是我实例化 @js 属性的代码:

class Context
  attr_reader :js, :partials, :helpers

  def initialize
    src = File.open(::Handlebars::Source.bundled_path, 'r').read
    @js = ExecJS.compile(src)
  end
end

这是一个显示问题的测试:

let(:ctx) { Hiptest::Handlebars::Context.new }

it "does not keep context properly (or I'm using the tool wrong" do
  ctx.js.eval('my_variable = 42')
  expect(ctx.js.eval('my_variable')).to eq(42)
end

现在当我运行它时:

rspec spec/handlebars_spec.rb:10                                                                   1 ↵
I, [2015-02-21T16:57:30.485774 #35939]  INFO -- : Not reporting to Code Climate because ENV['CODECLIMATE_REPO_TOKEN'] is not set.
Run options: include {:locations=>{"./spec/handlebars_spec.rb"=>[10]}}
F

Failures:

  1) Hiptest::Handlebars Context does not keep context properly (or I'm using the tool wrong
     Failure/Error: expect(ctx.js.eval('my_variable')).to eq(42)
     ExecJS::ProgramError:
       ReferenceError: Can't find variable: my_variable

注意:我在使用“exec”而不是“eval”时遇到了同样的问题。

这是一个愚蠢的例子。我真正想做的是运行“Handlebars.registerPartial”,然后再运行“Handlebars.compile”。但是,当尝试使用模板中的部分时,它会失败,因为之前注册的部分丢失了。

请注意,我找到了一种解决方法,但我觉得它很丑:/

  def register_partial(name, content)
    @partials[name] = content
  end

  def call(*args)
    @context.js.call([
      "(function (partials, helpers, tmpl, args) {",
      "  Object.keys(partials).forEach(function (key) {",
      "    Handlebars.registerPartial(key, partials[key]);",
      "  })",
      "  return Handlebars.compile(tmpl).apply(null, args);",
      "})"].join("\n"), @partials, @template, args)
  end

关于如何解决这个问题的任何想法?

【问题讨论】:

    标签: ruby execjs


    【解决方案1】:

    只有在调用 ExecJS.compile 时创建的上下文才会在 eval 之间保留。您想要保留的任何内容都需要成为初始编译的一部分。

    【讨论】:

    • 感谢您的解释。很抱歉花时间选择你的答案:/