diff --git a/package.json b/package.json index 5ea86417..dd80f192 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,9 @@ { "name": "@observablehq/runtime", - "version": "4.4.7", + "version": "4.5.0-rc.4", + "publishConfig": { + "tag": "next" + }, "license": "ISC", "main": "dist/runtime.umd.js", "module": "src/index.js", @@ -35,7 +38,7 @@ ], "dependencies": { "@observablehq/inspector": "^3.1.0", - "@observablehq/stdlib": "^3.0.0", + "@observablehq/stdlib": "3.2.0-rc.5", "esm": "^3.0.84" }, "devDependencies": { diff --git a/src/module.js b/src/module.js index 37567c9f..d8c6df12 100644 --- a/src/module.js +++ b/src/module.js @@ -6,14 +6,14 @@ import rethrow from "./rethrow"; import {variable_invalidation, variable_visibility} from "./runtime"; import Variable, {TYPE_DUPLICATE, TYPE_IMPLICIT, TYPE_NORMAL, no_observer} from "./variable"; -export default function Module(runtime, special) { +export default function Module(runtime, builtins = []) { Object.defineProperties(this, { _runtime: {value: runtime}, _scope: {value: new Map}, - _special: {value: new Map([ + _builtins: {value: new Map([ ["invalidation", variable_invalidation], ["visibility", variable_visibility], - ...special + ...builtins ])}, _source: {value: null, writable: true} }); @@ -27,7 +27,8 @@ Object.defineProperties(Module.prototype, { derive: {value: module_derive, writable: true, configurable: true}, import: {value: module_import, writable: true, configurable: true}, value: {value: module_value, writable: true, configurable: true}, - variable: {value: module_variable, writable: true, configurable: true} + variable: {value: module_variable, writable: true, configurable: true}, + builtin: {value: module_builtin, writable: true, configurable: true} }); function module_redefine(name) { @@ -63,7 +64,7 @@ async function module_value(name) { } function module_derive(injects, injectModule) { - var copy = new Module(this._runtime, this._special); + var copy = new Module(this._runtime, this._builtins); copy._source = this; forEach.call(injects, function(inject) { if (typeof inject !== "object") inject = {name: inject + ""}; @@ -101,7 +102,7 @@ function module_copy(copy, map) { sourceModule = sourceInput._module; copy.import(sourceInput._name, name, map.get(sourceModule) || (sourceModule._source - ? sourceModule._copy(new Module(copy._runtime, copy._special), map) // import-with + ? sourceModule._copy(new Module(copy._runtime, copy._builtins), map) // import-with : sourceModule)); } else { copy.define(name, source._inputs.map(variable_name), source._definition); @@ -114,8 +115,8 @@ function module_resolve(name) { var variable = this._scope.get(name), value; if (!variable) { variable = new Variable(TYPE_IMPLICIT, this); - if (this._special.has(name)) { - variable.define(name, this._special.get(name)); + if (this._builtins.has(name)) { + variable.define(name, constant(this._builtins.get(name))); } else if (this._runtime._builtin._scope.has(name)) { variable.import(name, this._runtime._builtin); } else { @@ -134,6 +135,10 @@ function module_resolve(name) { return variable; } +function module_builtin(name, value) { + this._builtins.set(name, value); +} + function variable_name(variable) { return variable._name; } diff --git a/src/runtime.js b/src/runtime.js index 3e1ada92..6e396c5c 100644 --- a/src/runtime.js +++ b/src/runtime.js @@ -1,4 +1,4 @@ -import {Library} from "@observablehq/stdlib"; +import {Library, FileAttachments} from "@observablehq/stdlib"; import {RuntimeError} from "./errors"; import generatorish from "./generatorish"; import load from "./load"; @@ -38,7 +38,8 @@ Object.defineProperties(Runtime.prototype, { _computeSoon: {value: runtime_computeSoon, writable: true, configurable: true}, _computeNow: {value: runtime_computeNow, writable: true, configurable: true}, dispose: {value: runtime_dispose, writable: true, configurable: true}, - module: {value: runtime_module, writable: true, configurable: true} + module: {value: runtime_module, writable: true, configurable: true}, + fileAttachments: {value: FileAttachments, writable: true, configurable: true} }); function runtime_dispose() { @@ -50,18 +51,18 @@ function runtime_dispose() { }); } -function runtime_module(define, observer = noop, special = {}) { +function runtime_module(define, observer = noop) { let module; if (define === undefined) { if (module = this._init) { this._init = null; return module; } - return new Module(this, Object.entries(special)); + return new Module(this); } module = this._modules.get(define); if (module) return module; - this._init = module = new Module(this, Object.entries(special)); + this._init = module = new Module(this); this._modules.set(define, module); try { define(this, observer); diff --git a/test/module/builtin-test.js b/test/module/builtin-test.js new file mode 100644 index 00000000..d18964d6 --- /dev/null +++ b/test/module/builtin-test.js @@ -0,0 +1,23 @@ +import {Runtime} from "../../src"; +import tape from "../tape"; +import valueof from "../variable/valueof"; + +tape("module.builtin(name, value) defines a module-specific builtin variable", async test => { + const runtime = new Runtime(); + const module = runtime.module(); + module.builtin("foo", 42); + const bar = module.variable(true).define("bar", ["foo"], foo => foo + 1); + await new Promise(setImmediate); + test.deepEqual(await valueof(bar), {value: 43}); +}); + +tape("module.builtin(name, value) can be overridden by a normal variable", async test => { + const runtime = new Runtime(); + const module = runtime.module(); + module.builtin("foo", 0); + const foo = module.variable(true).define("foo", [], () => 42); + const bar = module.variable(true).define("bar", ["foo"], foo => foo + 1); + await new Promise(setImmediate); + test.deepEqual(await valueof(foo), {value: 42}); + test.deepEqual(await valueof(bar), {value: 43}); +}); diff --git a/test/module/special-test.js b/test/module/special-test.js deleted file mode 100644 index f7a9fb3b..00000000 --- a/test/module/special-test.js +++ /dev/null @@ -1,30 +0,0 @@ -import {Runtime} from "../../src"; -import tape from "../tape"; -import valueof from "../variable/valueof"; -import noop from "../../src/noop"; - -tape("runtime.module(…, special) defines a module special variable", async test => { - const runtime = new Runtime(); - const module = runtime.module(noop, undefined, {foo: () => 42}); - const bar = module.variable(true).define("bar", ["foo"], foo => foo + 1); - await new Promise(setImmediate); - test.deepEqual(await valueof(bar), {value: 43}); -}); - -tape("runtime.module(…, special) can be a constant", async test => { - const runtime = new Runtime(); - const module = runtime.module(noop, undefined, {foo: 42}); - const bar = module.variable(true).define("bar", ["foo"], foo => foo + 1); - await new Promise(setImmediate); - test.deepEqual(await valueof(bar), {value: 43}); -}); - -tape("runtime.module(…, special) can be overridden by a normal variable", async test => { - const runtime = new Runtime(); - const module = runtime.module(noop, undefined, {foo: 0}); - const foo = module.variable(true).define("foo", [], () => 42); - const bar = module.variable(true).define("bar", ["foo"], foo => foo + 1); - await new Promise(setImmediate); - test.deepEqual(await valueof(foo), {value: 42}); - test.deepEqual(await valueof(bar), {value: 43}); -}); diff --git a/test/variable/derive-test.js b/test/variable/derive-test.js index 88a6f879..e514d2fa 100644 --- a/test/variable/derive-test.js +++ b/test/variable/derive-test.js @@ -1,7 +1,6 @@ import {Runtime} from "../../src/"; import tape from "../tape"; import valueof from "./valueof"; -import noop from "../../src/noop"; tape("module.derive(overrides, module) injects variables into a copied module", async test => { const runtime = new Runtime(); @@ -20,9 +19,10 @@ tape("module.derive(overrides, module) injects variables into a copied module", test.deepEqual(await valueof(d1), {value: 42}); }); -tape("module.derive(…) copies special variables", async test => { +tape("module.derive(…) copies module-specific builtins", async test => { const runtime = new Runtime(); - const module0 = runtime.module(noop, undefined, {a: 1}); + const module0 = runtime.module(); + module0.builtin("a", 1); const b0 = module0.variable(true).define("b", ["a"], a => a + 1); const module1_0 = module0.derive([], module0); const c1 = module1_0.variable(true).define("c", ["a"], a => a + 2); diff --git a/yarn.lock b/yarn.lock index 9f1a2da3..65b9b1e7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -25,13 +25,12 @@ dependencies: esm "^3.0.84" -"@observablehq/stdlib@^3.0.0": - version "3.1.1" - resolved "https://registry.yarnpkg.com/@observablehq/stdlib/-/stdlib-3.1.1.tgz#65e4368cba5920aa649c8c2a0c9d8f23bb51150f" - integrity sha512-lwt+ThlV5QIFg7WCIKn7IvCnGpEsGw8BkASPd5yyNZ7hU8gxubE7jOChVte8Lf+yMQmZsju55bCsk813+u4GxQ== +"@observablehq/stdlib@3.2.0-rc.5": + version "3.2.0-rc.5" + resolved "https://registry.yarnpkg.com/@observablehq/stdlib/-/stdlib-3.2.0-rc.5.tgz#e7b001d320ee8eb8d41f69fb37933e227d261dcc" + integrity sha512-qfNiq5il0jQiR9/gihZSBCI/kLaNBDHIrBcUI0aqYspXkz0D7ZJ45QZNwF/siLZVMYhUfmXWqjZb+JZ+034iMA== dependencies: - d3-require "^1.2.0" - esm "^3.0.84" + d3-require "^1.2.4" marked "https://github.com/observablehq/marked.git#94c6b946f462fd25db4465d71a6859183f86c57f" "@types/estree@*": @@ -329,10 +328,10 @@ cssstyle@^1.2.2: dependencies: cssom "0.3.x" -d3-require@^1.2.0: - version "1.2.3" - resolved "https://registry.yarnpkg.com/d3-require/-/d3-require-1.2.3.tgz#65a1c2137e69c5c442f1ca2a04f72a3965124c16" - integrity sha512-zfat3WTZRZmh7jCrTIhg4zZvivA0DZvez8lZq0JwYG9aW8LcSUFO4eiPnL5F2MolHcLE8CLfEt06sPP8N7y3AQ== +d3-require@^1.2.4: + version "1.2.4" + resolved "https://registry.npmjs.org/d3-require/-/d3-require-1.2.4.tgz#59afc591d5089f99fecd8c45ef7539e1fee112b3" + integrity sha512-8UseEGCkBkBxIMouLMPONUBmU8DUPC1q12LARV1Lk/2Jwa32SVgmRfX8GdIeR06ZP+CG85YD3N13K2s14qCNyA== dashdash@^1.12.0: version "1.14.1"