ClojureScript

Fix/enhance ^:export to work with properties that will be modified externally

Details

  • Type: Enhancement Enhancement
  • Status: Closed Closed
  • Priority: Major Major
  • Resolution: Declined
  • Affects Version/s: None
  • Fix Version/s: None
  • Component/s: None
  • Labels:
    None
  • Patch:
    Code

Description

Thin line between bug/enhancement here, but whatever...

Given this code:

(ns foo.bar)

(def ^:export baz 42)

(defn ^:export quux [] baz)

Advanced compilation yields code where baz is inlined, and even the property itself disappears. Whatever a downstream user/app/lib does to foo.bar.baz, quux will always return 42. Here's that code:

var d = this;
function f(g, e) {
  var b = g.split("."), a = d;
  b[0] in a || !a.execScript || a.execScript("var " + b[0]);
  for (var c;b.length && (c = b.shift());) {
    b.length || void 0 === e ? a = a[c] ? a[c] : a[c] = {} : a[c] = e;
  }
}
;f("foo.bar.baz", 42);
f("foo.bar.quux", function() {
  return 42;
});

Initially, I thought this was only because baz was a scalar, but the problem remains the same if an exported fn is returned by another fn; if the former is set to a different value downstream, the latter will continue returning the original that it closed over.

Based on this exchange with a GClosure compiler contributor, we need to use the @expose annotation on each exported property, and export the symbol for each intervening "namespace" segment in order to ensure that functions that refer to exported properties will return the same value that downstream users (might) mutate.

Activity

Chas Emerick made changes -
Field Original Value New Value
Patch Code [ 10001 ]
Attachment CLJS-670.patch [ 12460 ]
Chas Emerick made changes -
Resolution Declined [ 2 ]
Status Open [ 1 ] Closed [ 6 ]

People

Vote (0)
Watch (1)

Dates

  • Created:
    Updated:
    Resolved: