Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/source maps #1684

Open
wants to merge 60 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
3b3d8f5
🧩: add support for import-maps
merryman Aug 9, 2024
15a4fd3
🔁: add recast
merryman Aug 9, 2024
856a6d4
🌳: fix statementOf()
merryman Oct 2, 2024
b29d76b
❄️: add sourcemap support for bundler
merryman Oct 2, 2024
4548b05
🔁: fix linting for source transform capture code
merryman Oct 4, 2024
9c42167
🫓: support handling of npm: remapping dependencies in pkg.json
merryman Oct 27, 2024
e526b69
🔁🧑‍🏫❄️🧩: rename sourceMap -> importMAp
merryman Oct 28, 2024
dfa5658
🔁: switch to recast-x
merryman Oct 28, 2024
539203c
🔁: add babel module transform
merryman Dec 5, 2024
916bd7c
🔁: add babel dependencies
merryman Dec 5, 2024
a46ae16
🔁: add babel tests and make tests formatting independent
merryman Dec 5, 2024
065fa1b
🔁: merge babel transform visitor for improved performance
merryman Dec 5, 2024
02ebe41
☕️: bump chai and mocha
merryman Dec 5, 2024
68c09a5
🌳: support async param for nodes.funcExpr
merryman Dec 5, 2024
393ca3c
🧑‍🏫: add support for class transform to work with babel
merryman Dec 5, 2024
e058787
🧑‍🏫: add default acorn nodes to class transform
merryman Dec 5, 2024
a5d0ed3
🧑‍🏫: fix class template in transform sets
merryman Dec 5, 2024
a980e97
❄️: bump rollup
merryman Dec 5, 2024
887dbaa
❄️: fix bundling issue with babel modules
merryman Dec 5, 2024
76c4b31
🧩: fix esm regex to be more accurate
merryman Dec 5, 2024
b35b1ae
🧩: curb module updates if exportConflicts are present
merryman Dec 5, 2024
0c26221
❄️🧩🖥️: integrate babel transpiler
merryman Dec 5, 2024
6a680c5
🧩: avoid issues with json files in freezer bundles
merryman Dec 5, 2024
8cc25de
🧑‍🏫: fix broken objectLiteral ref
merryman Dec 5, 2024
2615890
🧑‍🏫: fix syntax error
merryman Dec 5, 2024
9a15d5f
🧑‍🏫: fix helper calls in transform
merryman Dec 6, 2024
dbea67d
🔁🧑‍🏫: remove recast
merryman Dec 6, 2024
542a68d
🔁: fix export conflict meta info injection
merryman Dec 6, 2024
f6b842a
🔁: fix missing ref capturing in assignments
merryman Dec 6, 2024
fb2fd02
🔁: fix some bugs in the acorn transforms
merryman Dec 9, 2024
7b235dc
🔁: remove recast and cleanup tests
merryman Dec 9, 2024
141e159
🌳: consider if statement blocks as separate scopes
merryman Dec 9, 2024
33133ae
🧑‍🏫: remove more recast references
merryman Dec 9, 2024
2c0ddef
❄️🪨🔁☕️: support esm:// syntax in import maps
merryman Dec 9, 2024
dcb2685
🔁: rename NumberLiteral -> NumericLiteral
merryman Dec 10, 2024
52597f1
🪨: fix esm resource exists()
merryman Dec 10, 2024
0d91023
🧩: fix esm module url resolution
merryman Dec 10, 2024
a474e4a
❄️: add rollup native build for linux
merryman Dec 10, 2024
8f343cd
🫓: update flatn
merryman Dec 10, 2024
6cf1ce1
☕️: add missing chai subset
merryman Dec 11, 2024
5cdde1d
📦: add format meta for packages-config
merryman Dec 11, 2024
3085680
🔁: fix ref replacement in babel transform
merryman Dec 11, 2024
7871bef
🌳🧑‍🏫🧩🎨📇: replace deep prop check with nested
merryman Dec 14, 2024
30adbf8
🧑‍🏫: adjust class transform in test
merryman Dec 14, 2024
06099f3
🧩: fix module tests
merryman Dec 14, 2024
fa22bf7
🎨: adjust render tests to work in non p3 envs
merryman Dec 14, 2024
2cb5dbb
🎨: adjust spec comparison
merryman Dec 14, 2024
3ecdf59
🧩: fix storing source maps in local storage
merryman Dec 16, 2024
d2e0efe
🧩: use fuzzy parse to check for mocha test
merryman Dec 16, 2024
c53939c
🔁: fix various bugs in the babel plugin
merryman Dec 16, 2024
1d46c8e
📙🖥️: fix some test issues
merryman Dec 16, 2024
63a284d
❄️🧰: delay linter module loading to improve loading time
merryman Dec 16, 2024
bb25019
👔: prevent protocol timeout error from crashing test run
merryman Dec 16, 2024
c80c9cc
🤕: properly await close call in case open() fails
merryman Dec 16, 2024
7189627
🧩: fix export lookup from frozen modules
merryman Dec 17, 2024
498c66c
🔁: silence dynamic import warning in babel
merryman Dec 18, 2024
3308bb8
🧑‍🏫: fix property fields handling in class transform
merryman Dec 18, 2024
5fc7d59
📦🧩🔁: switch to babel transpiler in server side
merryman Dec 18, 2024
f380909
🎨❄️🧩: remove systemjs-init related stuff that is no longer needed
merryman Dec 18, 2024
aa2a6b1
🧩🖥️: remove lively.transpiler references that are no longer needed
merryman Dec 18, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions flatn/dependencies.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ function depGraph (packageSpec, packageMap, dependencyFields = ['dependencies'])
let atIndex = nameAndVersion.lastIndexOf('@');
if (atIndex === -1) atIndex = nameAndVersion.length;
let name = nameAndVersion.slice(0, atIndex);
if (name.includes('@npm:')) name = name.split('@npm:')[1];
let version = nameAndVersion.slice(atIndex + 1);
let pSpec = packageMap.lookup(name, version);
if (!pSpec) throw new Error(`Cannot resolve package ${nameAndVersion}`);
Expand Down
35 changes: 26 additions & 9 deletions flatn/flatn-cjs.js
Original file line number Diff line number Diff line change
Expand Up @@ -15493,7 +15493,7 @@ const requestMap = {};

class ESMResource extends Resource {
static normalize (esmUrl) {
const id = esmUrl.replaceAll(/esm:\/\/(run|cache)\//g, '');
const id = esmUrl.replaceAll(/esm:\/\/([^\/]*)\//g, '');

let pathStructure = id.split('/').filter(Boolean);

Expand All @@ -15511,7 +15511,6 @@ class ESMResource extends Resource {
pathStructure.push(fileName);
}


if (pathStructure[pathStructure.length - 1].endsWith('+esm')) {
pathStructure[pathStructure.length - 1] = pathStructure[pathStructure.length - 1].replace('+esm', 'esm.js');
}
Expand All @@ -15527,13 +15526,22 @@ class ESMResource extends Resource {
return pathStructure;
}

async read () {
let module;

const id = this.url.replace(/esm:\/\/(run|cache)\//g, '');
let baseUrl = 'https://jspm.dev/';
getEsmURL () {
let baseUrl;
if (this.url.startsWith('esm://run/npm/')) baseUrl = 'https://cdn.jsdelivr.net/';
else if (this.url.startsWith('esm://run/')) baseUrl = 'https://esm.run/';
else if (this.url.startsWith('esm://cache/')) baseUrl = 'https://jspm.dev/';
else {
const domain = this.url.match(/esm:\/\/([^\/]*)\//)?.[1];
baseUrl = `https://${domain}/`;
}
return baseUrl;
}

async read () {
let module;
const id = this.url.replace(/esm:\/\/([^\/]*)\//g, '');
const esmURL = this.getEsmURL();

let pathStructure = ESMResource.normalize(id);

Expand All @@ -15544,7 +15552,7 @@ class ESMResource extends Resource {
if (typeof lively !== 'undefined' && (hit = lively.memory_esm?.get(shortName))) return await hit.blob.text();
module = await res.read();
} else {
module = await resource((baseUrl + id)).read();
module = await resource((esmURL + id)).read();
res.write(module);
}
return module;
Expand Down Expand Up @@ -15627,7 +15635,9 @@ class ESMResource extends Resource {
}

async exists () {
// stub that needs to exist
const id = this.url.replace(/esm:\/\/([^\/]*)\//g, '');
const baseUrl = this.getEsmURL();
return await resource(baseUrl).join(id).exists();
}

async remove () {
Expand Down Expand Up @@ -15706,6 +15716,9 @@ let fixGnuTar;

async function npmSearchForVersions (pname, range = '*') {
try {
if (range.startsWith('npm:')) {
[pname, range] = range.match(/npm:(.*)@(.*)/).slice(1);
}
pname = pname.replace(/\//g, '%2f');
// rms 18.6.18: npmjs.org seems to have dropped semver version resolution, so we do it by hand now
const { versions } = await resource(`http://registry.npmjs.org/${pname}/`).readJson();
Expand Down Expand Up @@ -16566,6 +16579,7 @@ function depGraph (packageSpec, packageMap, dependencyFields = ['dependencies'])
let atIndex = nameAndVersion.lastIndexOf('@');
if (atIndex === -1) atIndex = nameAndVersion.length;
let name = nameAndVersion.slice(0, atIndex);
if (name.includes('@npm:')) name = name.split('@npm:')[1];
let version = nameAndVersion.slice(atIndex + 1);
let pSpec = packageMap.lookup(name, version);
if (!pSpec) throw new Error(`Cannot resolve package ${nameAndVersion}`);
Expand Down Expand Up @@ -16915,6 +16929,9 @@ async function installPackage (

while (queue.length) {
let [name, version] = queue.shift();
if (version.startsWith('npm:')) {
[name, version] = version.match(/npm:(.*)@(.*)/).slice(1);
}
let installed = packageMap.lookup(name, version);

if (!installed) {
Expand Down
3 changes: 3 additions & 0 deletions flatn/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,9 @@ async function installPackage (

while (queue.length) {
let [name, version] = queue.shift();
if (version.startsWith('npm:')) {
[name, version] = version.match(/npm:(.*)@(.*)/).slice(1);
}
let installed = packageMap.lookup(name, version);

if (!installed) {
Expand Down
11 changes: 10 additions & 1 deletion flatn/module-resolver.js
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,16 @@ function flatnResolve (request, parentId = '', context = 'node') {
let packageMap = ensurePackageMap(packageCollectionDirs, individualPackageDirs, devPackageDirs);
let packageFound = packageMap.lookup(basename, deps[basename]) ||
packageMap.lookup(request, deps[request])/* for package names with "/" */;
let resolved = packageFound && findModuleInPackage(packageFound, basename, request, context);

let resolved;
if (!packageFound && deps[basename]?.startsWith('npm:')) {
let version;
[basename, version] = deps[basename].match(/npm:(.*)@(.*)/).slice(1);
packageFound = packageMap.lookup(basename, version);
resolved = packageFound && findModuleInPackage(packageFound, basename, basename, context);
} else {
resolved = packageFound && findModuleInPackage(packageFound, basename, request, context);
}

if (basename === '@empty') return '@empty';
if (basename && basename.match(/^https?\:\/\//)) return basename;
Expand Down
3 changes: 3 additions & 0 deletions flatn/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ let fixGnuTar;

async function npmSearchForVersions (pname, range = '*') {
try {
if (range.startsWith('npm:')) {
[pname, range] = range.match(/npm:(.*)@(.*)/).slice(1);
}
pname = pname.replace(/\//g, '%2f');
// rms 18.6.18: npmjs.org seems to have dropped semver version resolution, so we do it by hand now
const { versions } = await resource(`http://registry.npmjs.org/${pname}/`).readJson();
Expand Down
16 changes: 16 additions & 0 deletions lively.ast/lib/mozilla-ast-visitors.js
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,22 @@ class ScopeVisitor extends Visitor {
return node;
}

visitIfStatement (node, scope, path) {
const visitor = this;

node.test = visitor.accept(node.test, scope, path.concat(['test']));

const consequentScope = this.newScope(node, scope);
node.consequent = visitor.accept(node.consequent, consequentScope, path.concat(['consequent']));

if (node.alternate) {
const alternateScope = this.newScope(node, scope);
node.alternate = visitor.accept(node.alternate, alternateScope, path.concat(['alternate']));
}

return node;
}

visitLabeledStatement (node, scope, path) {
const visitor = this;
// ignore label
Expand Down
5 changes: 3 additions & 2 deletions lively.ast/lib/nodes.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ function binaryExpr (left, op, right) {
};
}

function funcExpr ({ arrow, id: funcId, expression, generator }, params = [], ...statements) {
function funcExpr ({ arrow, id: funcId, expression, generator, isAsync }, params = [], ...statements) {
// lively.ast.stringify(funcExpr({id: "foo"}, ["a"], exprStmt(id("3"))))
// // => "function foo(a) { 3; }"
params = params.map(ea => typeof ea === 'string' ? id(ea) : ea);
Expand All @@ -44,7 +44,8 @@ function funcExpr ({ arrow, id: funcId, expression, generator }, params = [], ..
? statements[0]
: { body: statements, type: 'BlockStatement' },
expression: expression || false,
generator: generator || false
generator: generator || false,
async: isAsync
};
}

Expand Down
2 changes: 1 addition & 1 deletion lively.ast/lib/query.js
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,7 @@ function statementOf (parsed, node, options) {
// Find the statement that a target node is in. Example:
// let source be "var x = 1; x + 1;" and we are looking for the
// Identifier "x" in "x+1;". The second statement is what will be found.
const nodes = nodesAt(node.start, parsed);
const nodes = nodesAt(node.start + 1, parsed);
const found = nodes.reverse().find(node => _stmtTypes.includes(node.type));
if (options && options.asPath) {
const v = new BaseVisitor(); let foundPath;
Expand Down
20 changes: 9 additions & 11 deletions lively.ast/tests/es6-test.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
/*global process, require, beforeEach, afterEach, describe, it*/
/* global process, require, beforeEach, afterEach, describe, it */

import { expect } from "mocha-es6";
import { expect } from 'mocha-es6';

import { parse } from "../lib/parser.js";
import { parse } from '../lib/parser.js';

describe('es6', function() {

it("arrow function", function() {
var code = '() => 23;'
var parsed = parse(code);
expect(parsed).deep.property("body[0].expression.type")
.equals("ArrowFunctionExpression");
describe('es6', function () {
it('arrow function', function () {
let code = '() => 23;';
let parsed = parse(code);
expect(parsed).has.nested.property('body[0].expression.type')
.equals('ArrowFunctionExpression');
});

});
69 changes: 32 additions & 37 deletions lively.ast/tests/parser-test.js
Original file line number Diff line number Diff line change
@@ -1,53 +1,48 @@
/*global beforeEach, afterEach, describe, it*/
/* global beforeEach, afterEach, describe, it */

import { expect } from "mocha-es6";
import { expect } from 'mocha-es6';

import { printAst } from "../lib/mozilla-ast-visitor-interface.js";
import { parse, parseFunction } from "../lib/parser.js";

describe('parse', function() {
import { printAst } from '../lib/mozilla-ast-visitor-interface.js';
import { parse, parseFunction } from '../lib/parser.js';

describe('parse', function () {
it('JavaScript code', () =>
expect(parse("1 + 2"))
.deep.property("body[0].type")
.equals("ExpressionStatement"));

describe("async / await", () => {

it("parses nested awaits", () => {
var src = "await (await foo()).bar()",
parsed = parse(src),
expected = ":Program(0-25)\n"
+ "\\-.body[0]:ExpressionStatement(0-25)\n"
+ " \\-.body[0].expression:AwaitExpression(0-25)\n"
+ " \\-.body[0].expression.argument:CallExpression(6-25)\n"
+ " \\-.body[0].expression.argument.callee:MemberExpression(6-23)\n"
+ " |-.body[0].expression.argument.callee.object:AwaitExpression(7-18)\n"
+ " | \\-.body[0].expression.argument.callee.object.argument:CallExpression(13-18)\n"
+ " | \\-.body[0].expression.argument.callee.object.argument.callee:Identifier(13-16)\n"
+ " \\-.body[0].expression.argument.callee.property:Identifier(20-23)"
expect(printAst(parsed, {printPositions: true})).to.equal(expected);
expect(parse('1 + 2'))
.nested.property('body[0].type')
.equals('ExpressionStatement'));

describe('async / await', () => {
it('parses nested awaits', () => {
let src = 'await (await foo()).bar()';
let parsed = parse(src);
let expected = ':Program(0-25)\n' +
'\\-.body[0]:ExpressionStatement(0-25)\n' +
' \\-.body[0].expression:AwaitExpression(0-25)\n' +
' \\-.body[0].expression.argument:CallExpression(6-25)\n' +
' \\-.body[0].expression.argument.callee:MemberExpression(6-23)\n' +
' |-.body[0].expression.argument.callee.object:AwaitExpression(7-18)\n' +
' | \\-.body[0].expression.argument.callee.object.argument:CallExpression(13-18)\n' +
' | \\-.body[0].expression.argument.callee.object.argument.callee:Identifier(13-16)\n' +
' \\-.body[0].expression.argument.callee.property:Identifier(20-23)';
expect(printAst(parsed, { printPositions: true })).to.equal(expected);
});

});

describe("parseFunction", () => {

it("anonmyous function", () => {
expect(parseFunction("function(x) { return x + 1; }").type).equals("FunctionExpression")
describe('parseFunction', () => {
it('anonmyous function', () => {
expect(parseFunction('function(x) { return x + 1; }').type).equals('FunctionExpression');
});

it("named function", () => {
expect(parseFunction("function foo(x) { return x + 1; }")).containSubset({type: "FunctionExpression", id: {name: "foo"}})
it('named function', () => {
expect(parseFunction('function foo(x) { return x + 1; }')).containSubset({ type: 'FunctionExpression', id: { name: 'foo' } });
});

it("arrow function", () => {
expect(parseFunction("(x) => { return x + 1; }")).containSubset({type: "ArrowFunctionExpression"})
it('arrow function', () => {
expect(parseFunction('(x) => { return x + 1; }')).containSubset({ type: 'ArrowFunctionExpression' });
});

it("short function", () => {
expect(parseFunction("x => x + 1")).containSubset({type: "ArrowFunctionExpression"})
it('short function', () => {
expect(parseFunction('x => x + 1')).containSubset({ type: 'ArrowFunctionExpression' });
});

});
});
Loading
Loading