@pleger/esa-js 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/GITHUB_USAGE.md +121 -0
- package/LICENSE +21 -0
- package/NPM_PUBLISH.md +51 -0
- package/PATTERNS.md +85 -0
- package/README.md +160 -0
- package/ROADMAP_10_STEPS.md +14 -0
- package/STEP1_TRIAGE.md +139 -0
- package/aspectscript-cli.js +61 -0
- package/aspectscript.js +1227 -0
- package/conformance/01-noBR-base-reentrancy.js +15 -0
- package/conformance/02-level-sensitive-cflow.js +19 -0
- package/conformance/03-scoping-strategy-d.js +20 -0
- package/conformance/04-jp-isolation-before-order.js +17 -0
- package/esa.js +904 -0
- package/index.d.ts +123 -0
- package/instrument.js +668 -0
- package/package.json +68 -0
- package/run-conformance.js +51 -0
- package/run-script.js +193 -0
- package/run-tests.js +236 -0
- package/transform-cache.js +54 -0
package/GITHUB_USAGE.md
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# AspectScript on GitHub
|
|
2
|
+
|
|
3
|
+
This guide explains how to use the repository from the command line and GitHub.
|
|
4
|
+
|
|
5
|
+
Repository:
|
|
6
|
+
- https://github.com/pleger/aspectscript
|
|
7
|
+
|
|
8
|
+
Playground (GitHub Pages):
|
|
9
|
+
- https://pleger.github.io/aspectscript/
|
|
10
|
+
|
|
11
|
+
## 1) Setup
|
|
12
|
+
|
|
13
|
+
Clone and install dependencies:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
git clone https://github.com/pleger/aspectscript.git
|
|
17
|
+
cd aspectscript
|
|
18
|
+
npm install
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## 2) Run scripts or examples from CLI
|
|
22
|
+
|
|
23
|
+
Use the script runner:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npm run run:script -- tests/test-ex.js
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
You can run any `.js` file with AspectScript support (AJS, PCs, Testing):
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
npm run run:script -- path/to/your-script.js
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Notes:
|
|
36
|
+
- `load(...)` lines are ignored automatically (for compatibility with legacy test files).
|
|
37
|
+
- The runner instruments JavaScript before execution, then runs it in an AspectScript-enabled VM context.
|
|
38
|
+
|
|
39
|
+
Export join point trace as machine-readable JSON:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
npm run run:script -- tests/test-ex.js --trace-json trace.json
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Disable transform cache:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
npm run run:script -- tests/test-ex.js --no-cache
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## 3) Use the AspectScript CLI command
|
|
52
|
+
|
|
53
|
+
You can also use the packaged CLI:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
npx aspectscript run tests/test-ex.js
|
|
57
|
+
npx aspectscript run tests/test-ex.js --trace-json trace.json
|
|
58
|
+
npx aspectscript run tests/test-ex.js --no-cache
|
|
59
|
+
npx aspectscript test
|
|
60
|
+
npx aspectscript test --cache-stats
|
|
61
|
+
npx aspectscript test --failed
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## 4) Run tests from CLI
|
|
65
|
+
|
|
66
|
+
Run all tests:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
npm test
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Run tests by prefix:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
node run-tests.js testDS
|
|
76
|
+
node run-tests.js testRee
|
|
77
|
+
node run-tests.js test21
|
|
78
|
+
node run-tests.js --cache-stats
|
|
79
|
+
node run-tests.js --no-cache
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## 5) Run only failed tests
|
|
83
|
+
|
|
84
|
+
After a test run, failed tests are written to `tests/lastFails.txt`.
|
|
85
|
+
|
|
86
|
+
Re-run only those failed tests:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
npm run test:failed
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Equivalent direct command:
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
node run-tests.js --failed
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## 6) Diagnostics
|
|
99
|
+
|
|
100
|
+
Runtime errors now include an AspectScript context line, for example:
|
|
101
|
+
|
|
102
|
+
```text
|
|
103
|
+
[AspectScript] join point: [exec: move] | level: 0 | receiver: Point
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
This helps identify where failures happen in advice/pointcut execution.
|
|
107
|
+
|
|
108
|
+
## 7) Citation
|
|
109
|
+
|
|
110
|
+
This implementation is based on:
|
|
111
|
+
|
|
112
|
+
Rodolfo Toledo, Paul Leger, and Eric Tanter. *AspectScript: Expressive Aspects for the Web*. AOSD'10, March 15-19, 2010, Rennes and St. Malo, France. ACM.
|
|
113
|
+
|
|
114
|
+
## 8) Conformance Suite
|
|
115
|
+
|
|
116
|
+
Run paper-aligned conformance scenarios:
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
npm run test:conformance
|
|
120
|
+
node run-conformance.js
|
|
121
|
+
```
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Paul Leger
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/NPM_PUBLISH.md
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# npm Publish Readiness
|
|
2
|
+
|
|
3
|
+
This project is configured for npm packaging, with:
|
|
4
|
+
- `main` entry (`aspectscript.js`)
|
|
5
|
+
- `types` entry (`index.d.ts`)
|
|
6
|
+
- `bin` command (`aspectscript`)
|
|
7
|
+
|
|
8
|
+
Current state:
|
|
9
|
+
- `package.json` is publish-ready (`"private": false`).
|
|
10
|
+
|
|
11
|
+
## Checklist
|
|
12
|
+
|
|
13
|
+
1. Set package metadata
|
|
14
|
+
|
|
15
|
+
```json
|
|
16
|
+
{
|
|
17
|
+
"name": "@pleger/esa-js",
|
|
18
|
+
"version": "0.2.0",
|
|
19
|
+
"description": "ESA-JS and AspectScript runtime and tooling",
|
|
20
|
+
"license": "MIT",
|
|
21
|
+
"repository": {
|
|
22
|
+
"type": "git",
|
|
23
|
+
"url": "https://github.com/pleger/ESA.git"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
2. Dry run package contents
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
npm pack --dry-run
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
3. Verify commands
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
npm test
|
|
38
|
+
npm run test:conformance
|
|
39
|
+
npx aspectscript --help
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
4. Publish
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
npm publish --access public
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Optional hardening
|
|
49
|
+
|
|
50
|
+
- Add `"files"` in `package.json` to control published artifacts explicitly.
|
|
51
|
+
- Add CI workflow for `npm test` + `npm run test:conformance` before release.
|
package/PATTERNS.md
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# AspectScript Patterns
|
|
2
|
+
|
|
3
|
+
This document gives practical patterns you can copy and adapt.
|
|
4
|
+
|
|
5
|
+
## 1) Logging all executions of a function
|
|
6
|
+
|
|
7
|
+
```js
|
|
8
|
+
function service() {
|
|
9
|
+
return 42;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
AJS.before(PCs.exec("service"), function (jp) {
|
|
13
|
+
console.log("[before]", String(jp), "args:", jp.args);
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
service();
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## 2) Enforce a simple authorization rule
|
|
20
|
+
|
|
21
|
+
```js
|
|
22
|
+
const session = { role: "guest" };
|
|
23
|
+
|
|
24
|
+
function deleteRecord() {
|
|
25
|
+
return "deleted";
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
AJS.around(PCs.exec("deleteRecord"), function (jp) {
|
|
29
|
+
if (session.role !== "admin") {
|
|
30
|
+
throw new Error("Not authorized");
|
|
31
|
+
}
|
|
32
|
+
return jp.proceed();
|
|
33
|
+
});
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## 3) Prevent recursive self-triggering with `noBR`
|
|
37
|
+
|
|
38
|
+
```js
|
|
39
|
+
function tick(n) {
|
|
40
|
+
if (n > 0) {
|
|
41
|
+
tick(n - 1);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
AJS.before(PCs.noBR(PCs.exec("tick")), function () {
|
|
46
|
+
console.log("advice once per recursion chain");
|
|
47
|
+
});
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## 4) Add explicit domain events
|
|
51
|
+
|
|
52
|
+
```js
|
|
53
|
+
AJS.before(PCs.event("save"), function (jp) {
|
|
54
|
+
console.log("save event", jp.recordId);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
AJS.event("save", { recordId: 42 }, function () {
|
|
58
|
+
// protected block
|
|
59
|
+
});
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## 5) Export trace data for tooling
|
|
63
|
+
|
|
64
|
+
```js
|
|
65
|
+
AJS.tracer.enable();
|
|
66
|
+
|
|
67
|
+
function runFlow() {
|
|
68
|
+
// your code
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
runFlow();
|
|
72
|
+
console.log(AJS.tracer.toJSON(true));
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Node CLI equivalent:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
npx aspectscript run your-script.js --trace-json trace.json
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## 6) Pitfalls to avoid
|
|
82
|
+
|
|
83
|
+
- Do not mutate shared join point fields expecting cross-advice visibility; ordering matters and tests rely on deterministic behavior.
|
|
84
|
+
- Use `AJS.down(...)` intentionally; lowering levels can re-introduce loops in badly scoped pointcuts.
|
|
85
|
+
- Prefer specific pointcuts (`PCs.exec("name")`) over catch-all predicates in performance-sensitive code.
|
package/README.md
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
# ESA / AspectScript
|
|
2
|
+
|
|
3
|
+
An implementation of ESA-JS (Expressive Stateful Aspects) and AspectScript for JavaScript.
|
|
4
|
+
|
|
5
|
+
## Quick start (npm)
|
|
6
|
+
|
|
7
|
+
Install:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @pleger/esa-js
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
### JavaScript example
|
|
14
|
+
|
|
15
|
+
```js
|
|
16
|
+
const AJS = require("@pleger/esa-js");
|
|
17
|
+
const PCs = AJS.Pointcuts;
|
|
18
|
+
|
|
19
|
+
AJS.before(PCs.event("purchase"), function (jp) {
|
|
20
|
+
console.log("purchase observed:", jp.orderId, jp.total);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
AJS.event("purchase", { orderId: "A-100", total: 42 }, function () {
|
|
24
|
+
console.log("inside purchase block");
|
|
25
|
+
});
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### TypeScript example
|
|
29
|
+
|
|
30
|
+
```ts
|
|
31
|
+
import AspectScript = require("@pleger/esa-js");
|
|
32
|
+
|
|
33
|
+
const AJS = AspectScript;
|
|
34
|
+
const PCs = AJS.Pointcuts;
|
|
35
|
+
|
|
36
|
+
AJS.around(PCs.event("audit"), (jp) => {
|
|
37
|
+
console.log("audit event:", jp.action);
|
|
38
|
+
return jp.proceed();
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
AJS.event("audit", { action: "DELETE_USER" }, () => {
|
|
42
|
+
console.log("business logic");
|
|
43
|
+
});
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Running instrumented scripts (`exec`, `call`, `get`, `set`, ...)
|
|
47
|
+
|
|
48
|
+
Use the CLI runner so your file is instrumented automatically:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
npx esa run your-script.js
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### ESA stateful example
|
|
55
|
+
|
|
56
|
+
```js
|
|
57
|
+
const AJS = require("@pleger/esa-js");
|
|
58
|
+
const ESA = AJS.ESA;
|
|
59
|
+
const PTs = ESA.Pointcuts;
|
|
60
|
+
|
|
61
|
+
function a(v) {}
|
|
62
|
+
function b() {}
|
|
63
|
+
|
|
64
|
+
const callA = PTs.call(a).and((jp, env) => env.bind("value", jp.args[0]));
|
|
65
|
+
|
|
66
|
+
const handler = ESA.deploy({
|
|
67
|
+
kind: ESA.BEFORE,
|
|
68
|
+
pattern: PTs.repeatUntil(callA, PTs.call(b)),
|
|
69
|
+
advice: (jp, env) => console.log("values:", env.value),
|
|
70
|
+
});
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## What is included
|
|
74
|
+
|
|
75
|
+
- A runtime and source instrumenter for AspectScript and ESA-JS.
|
|
76
|
+
- A Node-based test runner that executes the original `tests/test*.js` suite while ignoring legacy `load(...)` lines.
|
|
77
|
+
- A CLI command (`aspectscript`) for running scripts and tests.
|
|
78
|
+
- TypeScript type definitions (`index.d.ts`).
|
|
79
|
+
- A static playground in `docs/` with ESA-focused examples and:
|
|
80
|
+
- editable examples
|
|
81
|
+
- execution output
|
|
82
|
+
- join point tracing
|
|
83
|
+
|
|
84
|
+
## Local usage
|
|
85
|
+
|
|
86
|
+
Install dependencies:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
npm install
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Run the test suite:
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
npm test
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Run with cache statistics:
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
node run-tests.js --cache-stats
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Run only failed tests from the previous run:
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
npm run test:failed
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Run any script/example file with AspectScript runtime + instrumentation:
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
npm run run:script -- tests/test-ex.js
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Run and export execution trace as JSON:
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
npm run run:script -- tests/test-ex.js --trace-json trace.json
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Disable transform cache for a run:
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
npm run run:script -- tests/test-ex.js --no-cache
|
|
126
|
+
node run-tests.js --no-cache
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Run paper-aligned conformance examples:
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
npm run test:conformance
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Use the CLI command:
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
npx esa run tests/test-ex.js
|
|
139
|
+
npx esa test
|
|
140
|
+
npx esa test --failed
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Serve the playground locally from `docs/`:
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
cd docs
|
|
147
|
+
python3 -m http.server 4173
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Then open `http://127.0.0.1:4173`.
|
|
151
|
+
|
|
152
|
+
## GitHub guide
|
|
153
|
+
|
|
154
|
+
For a full command-line and GitHub usage guide, see [GITHUB_USAGE.md](./GITHUB_USAGE.md).
|
|
155
|
+
For practical examples/patterns, see [PATTERNS.md](./PATTERNS.md).
|
|
156
|
+
For package publishing readiness, see [NPM_PUBLISH.md](./NPM_PUBLISH.md).
|
|
157
|
+
|
|
158
|
+
## Current test status
|
|
159
|
+
|
|
160
|
+
The current implementation passes the full legacy suite plus ESA split-case tests.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# AspectScript 10-Step Roadmap Status
|
|
2
|
+
|
|
3
|
+
Last updated: March 17, 2026
|
|
4
|
+
|
|
5
|
+
1. Semantic parity with paper/tests: **Done** (`105/105` passing)
|
|
6
|
+
2. Reentrancy and advice-order hardening: **Done**
|
|
7
|
+
3. Scoping strategies explicit and testable: **Done** (runtime fixes + passing DS/DD tests)
|
|
8
|
+
4. Source-focused diagnostics: **Done** (runtime errors include join point/level/receiver context)
|
|
9
|
+
5. Machine-readable trace format: **Done** (`AJS.tracer.toJSON`, `AJS.tracer.saveToFile`, CLI `--trace-json`)
|
|
10
|
+
6. TypeScript typings: **Done** (`index.d.ts`)
|
|
11
|
+
7. npm package + CLI workflow: **In Progress** (`aspectscript` CLI ready; publish checklist added in `NPM_PUBLISH.md`)
|
|
12
|
+
8. Instrumentation/performance caching: **Done** (`.aspectscript-cache`, `--no-cache`, `--cache-stats`)
|
|
13
|
+
9. Conformance suite from paper examples: **Done** (`conformance/`, `run-conformance.js`, `npm run test:conformance`)
|
|
14
|
+
10. Practical docs and patterns: **Done** (`PATTERNS.md` + README/GitHub guide updates)
|
package/STEP1_TRIAGE.md
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# Step 1 Baseline and Triage (March 17, 2026)
|
|
2
|
+
|
|
3
|
+
This document captures the Step 1 deliverable of the plan:
|
|
4
|
+
- baseline run
|
|
5
|
+
- failure clustering by semantic root cause
|
|
6
|
+
- paper-backed expectations to guide fixes
|
|
7
|
+
|
|
8
|
+
Reference paper used for Step 1:
|
|
9
|
+
- `/Users/pleger/Downloads/1-s2.0-S0167642313002244-main.pdf`
|
|
10
|
+
- Tanter, Figueroa, Tabareau. *Execution levels for aspect-oriented programming* (Science of Computer Programming 80, 2014).
|
|
11
|
+
|
|
12
|
+
## 1) Baseline
|
|
13
|
+
|
|
14
|
+
Command:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
node run-tests.js
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Result:
|
|
21
|
+
- Evaluated: `105`
|
|
22
|
+
- Failed: `11`
|
|
23
|
+
|
|
24
|
+
Current failing tests:
|
|
25
|
+
- `test-ctx.js`
|
|
26
|
+
- `test-dd-03.js`
|
|
27
|
+
- `test-ss.js`
|
|
28
|
+
- `test15.js`
|
|
29
|
+
- `test21-modifyingJPData.js`
|
|
30
|
+
- `testDS06.js`
|
|
31
|
+
- `testRee01.js`
|
|
32
|
+
- `testRee02.js`
|
|
33
|
+
- `testRee03.js`
|
|
34
|
+
- `testRee04.js`
|
|
35
|
+
- `testRee16-jpOrder.js`
|
|
36
|
+
|
|
37
|
+
`tests/lastFails.txt` now reflects this baseline.
|
|
38
|
+
|
|
39
|
+
## 2) Paper-Guided Semantic Baseline
|
|
40
|
+
|
|
41
|
+
From the paper (used as guidance for expected behavior in this codebase):
|
|
42
|
+
- Execution levels are stratified; join points are emitted one level above current computation.
|
|
43
|
+
- Aspects affect join points one level below their deployment level.
|
|
44
|
+
- The default should defensively reduce regression risk.
|
|
45
|
+
- In AspectScript specifically, execution levels + reentrancy control should allow safe `down` usage without reintroducing loops.
|
|
46
|
+
- Control-flow reasoning should be level-sensitive (avoid conflating base computation and aspect/meta computation).
|
|
47
|
+
|
|
48
|
+
These principles map directly to current failing clusters around:
|
|
49
|
+
- reentrancy (`noBR`, `down`)
|
|
50
|
+
- cflow / parent-chain visibility
|
|
51
|
+
- scoping strategy and deployment propagation
|
|
52
|
+
|
|
53
|
+
## 3) Failure Clusters
|
|
54
|
+
|
|
55
|
+
### Cluster A: Deployment Scope and Join-Point Visibility
|
|
56
|
+
|
|
57
|
+
Tests:
|
|
58
|
+
- `test-ctx.js`
|
|
59
|
+
- `test-ss.js`
|
|
60
|
+
- `test15.js`
|
|
61
|
+
- `testDS06.js`
|
|
62
|
+
- `test-dd-03.js`
|
|
63
|
+
|
|
64
|
+
Observed symptoms:
|
|
65
|
+
- Missing expected `pr`/`call` join points in object-scoped scenarios.
|
|
66
|
+
- Unexpected extra matches in propagated/deployed contexts.
|
|
67
|
+
- Missing matches for interface-driven call pointcuts.
|
|
68
|
+
- Duplicate or leaked match in dynamic call/deployment path.
|
|
69
|
+
|
|
70
|
+
Primary hotspots in runtime:
|
|
71
|
+
- `currentVisibleAspects`, `aspectsFromLexicalContexts` in `aspectscript.js`
|
|
72
|
+
- frame construction in `wrap(...)` (lexical object/function visibility)
|
|
73
|
+
- propagation path (`computePropagation`, `pendingCalls`)
|
|
74
|
+
- strategy gates (`c`, `d`, `f`) in deployment evaluation
|
|
75
|
+
|
|
76
|
+
Working hypothesis:
|
|
77
|
+
- Aspect visibility and propagation across call/exec boundaries is inconsistent between lexical and dynamic paths, especially for `deployOn(...)` and strategy arrays.
|
|
78
|
+
|
|
79
|
+
### Cluster B: Advice Order and JP Data Isolation
|
|
80
|
+
|
|
81
|
+
Tests:
|
|
82
|
+
- `test21-modifyingJPData.js`
|
|
83
|
+
- `testRee16-jpOrder.js`
|
|
84
|
+
|
|
85
|
+
Observed symptoms:
|
|
86
|
+
- Advice ordering mismatch (`before` behaves as LIFO where tests expect FIFO).
|
|
87
|
+
- cflow/order interaction includes join point `z` when it should be excluded.
|
|
88
|
+
|
|
89
|
+
Primary hotspots in runtime:
|
|
90
|
+
- chain construction loop in `weave(...)` for `before`/`around`
|
|
91
|
+
- cflow parent traversal and ordering assumptions
|
|
92
|
+
|
|
93
|
+
Working hypothesis:
|
|
94
|
+
- Advice chain composition order is inverted for `before`.
|
|
95
|
+
- Parent/cflow timing around `before` advice execution may conflate pre-body advice activity with function execution context.
|
|
96
|
+
|
|
97
|
+
### Cluster C: Reentrancy and Execution Levels (`noBR` + `down`)
|
|
98
|
+
|
|
99
|
+
Tests:
|
|
100
|
+
- `testRee01.js`
|
|
101
|
+
- `testRee02.js`
|
|
102
|
+
- `testRee03.js`
|
|
103
|
+
- `testRee04.js`
|
|
104
|
+
|
|
105
|
+
Observed symptoms:
|
|
106
|
+
- Expected advice does not fire at all (over-suppression).
|
|
107
|
+
- `noBR(...)` and `down(...)` interplay blocks legitimate first matches.
|
|
108
|
+
- Context-aware `noBR(pc, ctx)` case suppresses all hits instead of one-per-context behavior.
|
|
109
|
+
|
|
110
|
+
Primary hotspots in runtime:
|
|
111
|
+
- `Pointcuts.noBR(...)`
|
|
112
|
+
- `down(...)` and `isSuppressed(...)`
|
|
113
|
+
- level bookkeeping (`state.currentLevel`, `state.downStack`)
|
|
114
|
+
|
|
115
|
+
Working hypothesis:
|
|
116
|
+
- Reentrancy suppression tokening and/or stack scanning is too aggressive.
|
|
117
|
+
- Level suppression may be applied before initial legitimate match is recorded.
|
|
118
|
+
|
|
119
|
+
## 4) Step 2 Entry Strategy (from this triage)
|
|
120
|
+
|
|
121
|
+
Recommended fix order:
|
|
122
|
+
1. Fix deterministic advice ordering in `weave(...)` (lowest-risk, unblocks JP-order tests).
|
|
123
|
+
2. Fix `noBR`/`down` suppression semantics (Ree cluster).
|
|
124
|
+
3. Fix deployment propagation and strategy visibility (`deployOn`, `c/d/f`, lexical vs dynamic environments).
|
|
125
|
+
|
|
126
|
+
Validation workflow:
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
node run-tests.js --failed
|
|
130
|
+
node run-tests.js testRee
|
|
131
|
+
node run-tests.js test-ctx
|
|
132
|
+
node run-tests.js test-ss
|
|
133
|
+
node run-tests.js test-dd-03
|
|
134
|
+
node run-tests.js testDS06
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Exit criteria for Step 2 start:
|
|
138
|
+
- each cluster has one targeted failing test used as a guard during implementation
|
|
139
|
+
- full suite run after each cluster fix
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const path = require("path");
|
|
4
|
+
const { spawnSync } = require("child_process");
|
|
5
|
+
|
|
6
|
+
function runNodeScript(scriptName, args) {
|
|
7
|
+
const scriptPath = path.join(__dirname, scriptName);
|
|
8
|
+
const result = spawnSync(process.execPath, [scriptPath].concat(args), {
|
|
9
|
+
stdio: "inherit",
|
|
10
|
+
});
|
|
11
|
+
if (typeof result.status === "number") {
|
|
12
|
+
process.exitCode = result.status;
|
|
13
|
+
} else {
|
|
14
|
+
process.exitCode = 1;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function usage() {
|
|
19
|
+
process.stdout.write(
|
|
20
|
+
"AspectScript CLI\n" +
|
|
21
|
+
"\n" +
|
|
22
|
+
"Usage:\n" +
|
|
23
|
+
" aspectscript run <file.js> [--trace-json trace.json] [--no-cache]\n" +
|
|
24
|
+
" aspectscript test [--failed|-f] [--cache-stats] [--no-cache] [testPrefix...]\n" +
|
|
25
|
+
"\n" +
|
|
26
|
+
"Examples:\n" +
|
|
27
|
+
" aspectscript run tests/test-ex.js\n" +
|
|
28
|
+
" aspectscript run tests/test-ex.js --trace-json trace.json\n" +
|
|
29
|
+
" aspectscript run tests/test-ex.js --no-cache\n" +
|
|
30
|
+
" aspectscript test\n" +
|
|
31
|
+
" aspectscript test --cache-stats\n" +
|
|
32
|
+
" aspectscript test --failed\n" +
|
|
33
|
+
" aspectscript test testRee\n"
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function main() {
|
|
38
|
+
const args = process.argv.slice(2);
|
|
39
|
+
const command = args[0];
|
|
40
|
+
|
|
41
|
+
if (!command || command === "-h" || command === "--help") {
|
|
42
|
+
usage();
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (command === "run") {
|
|
47
|
+
runNodeScript("run-script.js", args.slice(1));
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (command === "test") {
|
|
52
|
+
runNodeScript("run-tests.js", args.slice(1));
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
process.stderr.write("Unknown command: " + command + "\n\n");
|
|
57
|
+
usage();
|
|
58
|
+
process.exitCode = 1;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
main();
|