Skip to content

Commit

Permalink
fix: Cleaner parser / interpreter
Browse files Browse the repository at this point in the history
Fix "this" edge conditions

Signed-off-by: Gordon Smith <GordonJSmith@gmail.com>
  • Loading branch information
GordonSmith committed Aug 31, 2022
1 parent a231820 commit 02e2a2b
Show file tree
Hide file tree
Showing 18 changed files with 1,050 additions and 214 deletions.
4 changes: 3 additions & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ module.exports = {
max: 1
}
],

"no-console": [1, {
"allow": ["info", "warn", "error"]
}],
"func-call-spacing": ["error", "never"],
"space-before-function-paren": ["error", {
"anonymous": "always",
Expand Down
3 changes: 2 additions & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@
"${workspaceRoot}\\samples"
],
"outFiles": [
"${workspaceRoot}/src/**/*.js"
"${workspaceRoot}/src/**/*.js",
"${workspaceRoot}/src/notebook/renderers/**/*.js"
],
},
{
Expand Down
352 changes: 160 additions & 192 deletions package-lock.json

Large diffs are not rendered by default.

20 changes: 10 additions & 10 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"version": "0.4.16",
"publisher": "GordonSmith",
"displayName": "Observable JS",
"description": "Interpreter for ObservableHQ Notebooks",
"description": "Interpreter for ObservableHQ Notebooks - Includes VS Code Notebooks with Observale, Observable \"Markdown\" files with embedded Observable (.omd) and Observable \"JavaScript\" files.",
"icon": "images/ObservableJS.png",
"categories": [
"Programming Languages",
Expand Down Expand Up @@ -52,9 +52,9 @@
"@hpcc-js/common": "2.71.1",
"@hpcc-js/observable-md": "2.53.1",
"@hpcc-js/util": "2.49.0",
"@observablehq/inspector": "3.2.4",
"@observablehq/parser": "6.0.0",
"@observablehq/runtime": "4.23.0",
"@observablehq/inspector": "3.2.4",
"@observablehq/stdlib": "3.19.8",
"@rollup/plugin-alias": "3.1.9",
"@rollup/plugin-commonjs": "22.0.2",
Expand All @@ -64,31 +64,31 @@
"@types/node": "16.11.56",
"@types/vscode": "1.70.0",
"@types/vscode-notebook-renderer": "1.60.0",
"@typescript-eslint/eslint-plugin": "5.34.0",
"@typescript-eslint/parser": "5.34.0",
"@typescript-eslint/eslint-plugin": "5.36.1",
"@typescript-eslint/parser": "5.36.1",
"@vscode/extension-telemetry": "0.6.2",
"acorn": "8.8.0",
"acorn-walk": "^8.2.0",
"assert": "2.0.0",
"browserify-zlib": "0.2.0",
"buffer": "6.0.3",
"css-loader": "6.7.1",
"eslint": "8.22.0",
"eslint": "8.23.0",
"mocha": "10.0.0",
"node-fetch": "3.2.10",
"npm-run-all": "4.1.5",
"os-browserify": "0.3.0",
"path-browserify": "1.0.1",
"rimraf": "3.0.2",
"rollup": "2.78.1",
"rollup": "2.79.0",
"rollup-plugin-postcss": "4.0.2",
"rollup-plugin-sourcemaps": "0.6.3",
"source-map-loader": "4.0.0",
"standard-version": "9.5.0",
"stream-browserify": "3.0.0",
"style-loader": "3.3.1",
"tslib": "2.4.0",
"typescript": "4.7.4",
"vsce": "2.10.2",
"typescript": "4.8.2",
"vsce": "2.11.0",
"vscode-test": "1.6.1",
"webpack": "5.74.0",
"webpack-cli": "4.10.0"
Expand Down Expand Up @@ -364,4 +364,4 @@
}
]
}
}
}
2 changes: 1 addition & 1 deletion rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export default [{
},
plugins: plugins
}, {
input: "./lib-es6/notebook-renderers/ojsRenderer",
input: "./lib-es6/notebook/renderers/index",
output: [{
file: "dist/ojsRenderer.js",
format: "es",
Expand Down
6 changes: 3 additions & 3 deletions samples/test.ojsnb
Original file line number Diff line number Diff line change
Expand Up @@ -147,15 +147,15 @@
},
{
"id": 1,
"value": "mutable xxx = zzz;",
"value": "mutable xxx = ()=>zzz;",
"pinned": true,
"mode": "js",
"data": null,
"name": ""
},
{
"id": 2,
"value": "xxx",
"value": "mutable xxx()",
"pinned": true,
"mode": "js",
"data": null,
Expand All @@ -179,7 +179,7 @@
},
{
"id": 5,
"value": "++mutable xxx",
"value": "++mutable xxx()",
"pinned": true,
"mode": "js",
"data": null,
Expand Down
101 changes: 101 additions & 0 deletions src/compiler/cell.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import { Inspector } from "@observablehq/inspector";
import { observablehq as ohq } from "./types";
import { Notebook } from "./notebook";
import { parseCell } from "./parser";
import { obfuscatedImport } from "./util";

export class Cell {

protected _notebook: Notebook;
protected _variable: ohq.Variable; // Regular variable
protected _initialValue: ohq.Variable; // Cell is "mutable"
protected _variableValue: ohq.Variable; // Cell is a "viewof" or "mutable"
protected _imported: { variable: ohq.Variable, variableValue?: ohq.Variable }[]; // Cell is an import
protected _observer: ohq.InspectorFactory;

constructor(notebook: Notebook, observer: ohq.InspectorFactory) {
this._notebook = notebook;
this._observer = observer;
}

reset() {
this._imported?.forEach(v => {
v.variable.delete();
v.variableValue?.delete();
});
this._initialValue?.delete();
this._variable?.delete();
this._variableValue?.delete();
}

dispose() {
this.reset();
}

async importFile(partial) {
// TODO ---
// const path = join(this._folder, partial);
// let ojs = await this.fetchUrl(path);
// if (partial.indexOf(".omd") > 1) {
// ojs = omd2ojs(ojs).ojsArr.map(row => row.ojs).join("\n");
// }

// const context = this;
// return {
// default: function define(runtime, observer) {
// const newModule = runtime.module();
// const ojsModule = new OJSModule(context._ojsRuntime, partial, newModule, ojs, dirname(path));
// ojsModule.parse(true);
// }
// };
}

protected async importNotebook(partial) {
return obfuscatedImport(`https://api.observablehq.com/${partial[0] === "@" ? partial : `d/${partial}`}.js?v=3`);
}

async interpret(cellSource: string) {
this.reset();

const parsed = parseCell(cellSource);
if (parsed.import) {
const impMod: any = [".", "/"].indexOf(parsed.import.src[0]) === 0 ?
await this.importFile(parsed.import.src) :
await this.importNotebook(parsed.import.src);

let mod = this._notebook.createModule(impMod.default);
if (parsed.import.injections.length) {
mod = mod.derive(parsed.import.injections, this._notebook.main());
}

this._imported = parsed.import.specifiers.map(spec => {
const viewof = spec.view ? "viewof " : "";
const retVal = {
variable: this._notebook.importVariable(viewof + spec.name, viewof + spec.alias, mod),
variableValue: undefined
};
if (spec.view) {
retVal.variableValue = this._notebook.importVariable(spec.name, spec.alias, mod);
}
return retVal;
});
this._variable = this._notebook.createVariable(this._observer());
this._variable.define(undefined, ["md"], md => {
return md`\`\`\`JavaScript
${cellSource}
\`\`\``;
});
} else {
if (parsed.initialValue) {
this._initialValue = this._notebook.createVariable();
this._initialValue.define(parsed.initialValue.id, parsed.initialValue.inputs, parsed.initialValue.func);
}
this._variable = this._notebook.createVariable(this._observer(parsed.id));
this._variable.define(parsed.id, parsed.inputs, parsed.func);
if (parsed.viewofValue) {
this._variableValue = this._notebook.createVariable(parsed.initialValue && this._observer(parsed.viewofValue.id));
this._variableValue.define(parsed.viewofValue.id, parsed.viewofValue.inputs, parsed.viewofValue.func);
}
}
}
}
60 changes: 60 additions & 0 deletions src/compiler/notebook.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { Runtime, Library } from "@observablehq/runtime";
import { FileAttachments } from "@observablehq/stdlib";
import { Cell } from "./cell";
import { observablehq as ohq } from "./types";

export class Notebook {

protected _runtime: ohq.Runtime;
protected _main: ohq.Module;

constructor(notebook?: ohq.Notebook, plugins: object = {}) {
const files = {};
notebook?.files?.forEach(f => files[f.name] = f.url);

const library = new Library();
library.FileAttachment = function () {
return FileAttachments(name => {
return files[name];
});
};

const domDownload = library.DOM.download;
library.DOM.download = function (blob, file) {
return domDownload(blob, files[file]);
};

this._runtime = new Runtime({ ...library, ...plugins });
this._main = this._runtime.module();
}

dispose() {
this._runtime.dispose();
delete this._runtime;
delete this._main;
}

createCell(inspector: ohq.InspectorFactory): Cell {
return new Cell(this, inspector);
}

// ObservableHQ ---
main(): ohq.Module {
return this._main;
}

createModule(define): ohq.Module {
return this._runtime.module(define);
}

createVariable(inspector?: ohq.Inspector): ohq.Variable {
return this._main.variable(inspector);
}

importVariable(name: string, alias: string, otherModule: ohq.Module): ohq.Variable {
return this._main.import(name, alias, otherModule);
}

removeCell(id: string) {
}
}
Loading

0 comments on commit 02e2a2b

Please sign in to comment.