Skip to content

Commit

Permalink
improve
Browse files Browse the repository at this point in the history
  • Loading branch information
liuxingbaoyu committed Sep 12, 2023
1 parent 0effd92 commit 376555f
Show file tree
Hide file tree
Showing 24 changed files with 291 additions and 147 deletions.
4 changes: 4 additions & 0 deletions packages/babel-helpers/src/helpers-generated.ts
Expand Up @@ -93,6 +93,10 @@ export default Object.freeze({
"7.22.0",
'export default function _using(o,e,n){if(null==e)return e;if("object"!=typeof e)throw new TypeError("using declarations can only be used with objects, null, or undefined.");if(n)var r=e[Symbol.asyncDispose||Symbol.for("Symbol.asyncDispose")];if(null==r&&(r=e[Symbol.dispose||Symbol.for("Symbol.dispose")]),"function"!=typeof r)throw new TypeError("Property [Symbol.dispose] is not a function.");return o.push({v:e,d:r,a:n}),e}',
),
usingCtx: helper(
"7.23.0",
'function dispose_SuppressedError(r,e){return"undefined"!=typeof SuppressedError?dispose_SuppressedError=SuppressedError:(dispose_SuppressedError=function(r,e){this.suppressed=r,this.error=e,this.stack=(new Error).stack},dispose_SuppressedError.prototype=Object.create(Error.prototype,{constructor:{value:dispose_SuppressedError,writable:!0,configurable:!0}})),new dispose_SuppressedError(r,e)}export default function _usingCtx(){var r={};return{s:[],e:r,using:function(r,e){if(null==r)return r;if("object"!=typeof r)throw new TypeError("using declarations can only be used with objects, null, or undefined.");if(e)var s=r[Symbol.asyncDispose||Symbol.for("Symbol.asyncDispose")];if(null==s&&(s=r[Symbol.dispose||Symbol.for("Symbol.dispose")]),"function"!=typeof s)throw new TypeError("Property [Symbol.dispose] is not a function.");return this.s.push({v:r,d:s,a:e}),r},dispose:function(){var e=this.s,s=this.e;function next(){for(;o=e.pop();)try{var o,t=o.d.call(o.v);if(o.a)return Promise.resolve(t).then(next,err)}catch(r){return err(r)}if(s!=r)throw s}function err(e){return s=s!=r?new dispose_SuppressedError(e,s):e,next()}return next()}}}',
),
wrapRegExp: helper(
"7.19.0",
'import setPrototypeOf from"setPrototypeOf";import inherits from"inherits";export default function _wrapRegExp(){_wrapRegExp=function(e,r){return new BabelRegExp(e,void 0,r)};var e=RegExp.prototype,r=new WeakMap;function BabelRegExp(e,t,p){var o=new RegExp(e,t);return r.set(o,p||r.get(e)),setPrototypeOf(o,BabelRegExp.prototype)}function buildGroups(e,t){var p=r.get(t);return Object.keys(p).reduce((function(r,t){var o=p[t];if("number"==typeof o)r[t]=e[o];else{for(var i=0;void 0===e[o[i]]&&i+1<o.length;)i++;r[t]=e[o[i]]}return r}),Object.create(null))}return inherits(BabelRegExp,RegExp),BabelRegExp.prototype.exec=function(r){var t=e.exec.call(this,r);if(t){t.groups=buildGroups(t,this);var p=t.indices;p&&(p.groups=buildGroups(p,this))}return t},BabelRegExp.prototype[Symbol.replace]=function(t,p){if("string"==typeof p){var o=r.get(this);return e[Symbol.replace].call(this,t,p.replace(/\\$<([^>]+)>/g,(function(e,r){var t=o[r];return"$"+(Array.isArray(t)?t.join("$"):t)})))}if("function"==typeof p){var i=this;return e[Symbol.replace].call(this,t,(function(){var e=arguments;return"object"!=typeof e[e.length-1]&&(e=[].slice.call(e)).push(buildGroups(e,i)),p.apply(this,e)}))}return e[Symbol.replace].call(this,t,p)},_wrapRegExp.apply(this,arguments)}',
Expand Down
76 changes: 76 additions & 0 deletions packages/babel-helpers/src/helpers/usingCtx.js
@@ -0,0 +1,76 @@
/* @minVersion 7.23.0 */

function dispose_SuppressedError(suppressed, error) {
if (typeof SuppressedError !== "undefined") {
// eslint-disable-next-line no-undef
dispose_SuppressedError = SuppressedError;
} else {
dispose_SuppressedError = function SuppressedError(suppressed, error) {
this.suppressed = suppressed;
this.error = error;
this.stack = new Error().stack;
};
dispose_SuppressedError.prototype = Object.create(Error.prototype, {
constructor: {
value: dispose_SuppressedError,
writable: true,
configurable: true,
},
});
}
return new dispose_SuppressedError(suppressed, error);
}

export default function _usingCtx() {
var empty = {};
return {
s: [], // stack
e: empty, // error
using: function (value, isAwait) {
if (value === null || value === void 0) return value;
if (typeof value !== "object") {
throw new TypeError(
"using declarations can only be used with objects, null, or undefined."
);
}
// core-js-pure uses Symbol.for for polyfilling well-known symbols
if (isAwait) {
var dispose =
value[Symbol.asyncDispose || Symbol.for("Symbol.asyncDispose")];
}
if (dispose === null || dispose === void 0) {
dispose = value[Symbol.dispose || Symbol.for("Symbol.dispose")];
}
if (typeof dispose !== "function") {
throw new TypeError(`Property [Symbol.dispose] is not a function.`);
}
this.s.push({ v: value, d: dispose, a: isAwait });
return value;
},
dispose: function () {
var stack = this.s,
error = this.e;

function next() {
while ((r = stack.pop())) {
try {
var r,
p = r.d.call(r.v);
if (r.a) return Promise.resolve(p).then(next, err);
} catch (e) {
return err(e);
}
}
if (error != empty) throw error;
}

function err(e) {
error = error != empty ? new dispose_SuppressedError(e, error) : e;

return next();
}

return next();
},
};
}
Expand Up @@ -43,38 +43,94 @@ export default declare(api => {
path: NodePath<t.BlockStatement | t.StaticBlock>,
state,
) {
let stackId: t.Identifier | null = null;
let needsAwait = false;

for (const node of path.node.body) {
if (!isUsingDeclaration(node)) continue;
stackId ??= path.scope.generateUidIdentifier("stack");
const isAwaitUsing =
node.kind === "await using" ||
TOP_LEVEL_USING.get(node) === USING_KIND.AWAIT;
needsAwait ||= isAwaitUsing;

if (!TOP_LEVEL_USING.delete(node)) {
node.kind = "const";
if (state.availableHelper("usingCtx")) {
let ctx: t.Identifier | null = null;
let needsAwait = false;

for (const node of path.node.body) {
if (!isUsingDeclaration(node)) continue;
ctx ??= path.scope.generateUidIdentifier("usingCtx");
const isAwaitUsing =
node.kind === "await using" ||
TOP_LEVEL_USING.get(node) === USING_KIND.AWAIT;
needsAwait ||= isAwaitUsing;

if (!TOP_LEVEL_USING.delete(node)) {
node.kind = "const";
}
node.declarations.forEach(decl => {
const args = [decl.init];
if (isAwaitUsing) args.push(t.booleanLiteral(true));
decl.init = t.callExpression(
t.memberExpression(t.cloneNode(ctx), t.identifier("using")),
args,
);
});
}
node.declarations.forEach(decl => {
const args = [t.cloneNode(stackId), decl.init];
if (isAwaitUsing) args.push(t.booleanLiteral(true));
decl.init = t.callExpression(state.addHelper("using"), args);
});
}
if (!stackId) return;
if (!ctx) return;

const errorId = path.scope.generateUidIdentifier("error");
const hasErrorId = path.scope.generateUidIdentifier("hasError");
let disposeCall: t.Expression = t.callExpression(
t.memberExpression(t.cloneNode(ctx), t.identifier("dispose")),
[],
);
if (needsAwait) disposeCall = t.awaitExpression(disposeCall);

let disposeCall: t.Expression = t.callExpression(
state.addHelper("dispose"),
[t.cloneNode(stackId), t.cloneNode(errorId), t.cloneNode(hasErrorId)],
);
if (needsAwait) disposeCall = t.awaitExpression(disposeCall);
const replacement = template.statement.ast`
try {
var ${t.cloneNode(ctx)} = ${state.addHelper("usingCtx")}();
${path.node.body}
} catch (_) {
${t.cloneNode(ctx)}.e = _;
} finally {
${disposeCall}
}
`;

const replacement = template.statement.ast`
const { parentPath } = path;
if (
parentPath.isFunction() ||
parentPath.isTryStatement() ||
parentPath.isCatchClause()
) {
path.replaceWith(t.blockStatement([replacement]));
} else if (path.isStaticBlock()) {
path.node.body = [replacement];
} else {
path.replaceWith(replacement);
}
} else {
let stackId: t.Identifier | null = null;
let needsAwait = false;

for (const node of path.node.body) {
if (!isUsingDeclaration(node)) continue;
stackId ??= path.scope.generateUidIdentifier("stack");
const isAwaitUsing =
node.kind === "await using" ||
TOP_LEVEL_USING.get(node) === USING_KIND.AWAIT;
needsAwait ||= isAwaitUsing;

if (!TOP_LEVEL_USING.delete(node)) {
node.kind = "const";
}
node.declarations.forEach(decl => {
const args = [t.cloneNode(stackId), decl.init];
if (isAwaitUsing) args.push(t.booleanLiteral(true));
decl.init = t.callExpression(state.addHelper("using"), args);
});
}
if (!stackId) return;

const errorId = path.scope.generateUidIdentifier("error");
const hasErrorId = path.scope.generateUidIdentifier("hasError");

let disposeCall: t.Expression = t.callExpression(
state.addHelper("dispose"),
[t.cloneNode(stackId), t.cloneNode(errorId), t.cloneNode(hasErrorId)],
);
if (needsAwait) disposeCall = t.awaitExpression(disposeCall);

const replacement = template.statement.ast`
try {
var ${stackId} = [];
${path.node.body}
Expand All @@ -86,17 +142,18 @@ export default declare(api => {
}
`;

const { parentPath } = path;
if (
parentPath.isFunction() ||
parentPath.isTryStatement() ||
parentPath.isCatchClause()
) {
path.replaceWith(t.blockStatement([replacement]));
} else if (path.isStaticBlock()) {
path.node.body = [replacement];
} else {
path.replaceWith(replacement);
const { parentPath } = path;
if (
parentPath.isFunction() ||
parentPath.isTryStatement() ||
parentPath.isCatchClause()
) {
path.replaceWith(t.blockStatement([replacement]));
} else if (path.isStaticBlock()) {
path.node.body = [replacement];
} else {
path.replaceWith(replacement);
}
}
},
};
Expand Down
Expand Up @@ -3,14 +3,13 @@ function fn() {
return (_fn = _fn || babelHelpers.asyncToGenerator(function* () {
yield 0;
try {
var _stack = [];
const x = babelHelpers.using(_stack, y, true);
var _usingCtx = babelHelpers.usingCtx();
const x = _usingCtx.using(y, true);
yield 1;
} catch (_) {
var _error = _;
var _hasError = true;
_usingCtx.e = _;
} finally {
yield babelHelpers.dispose(_stack, _error, _hasError);
yield _usingCtx.dispose();
}
})).apply(this, arguments);
}
@@ -1,11 +1,10 @@
try {
var _stack = [];
const a = babelHelpers.using(_stack, 1);
const b = babelHelpers.using(_stack, 2, true);
const c = babelHelpers.using(_stack, 3);
var _usingCtx = babelHelpers.usingCtx();
const a = _usingCtx.using(1);
const b = _usingCtx.using(2, true);
const c = _usingCtx.using(3);
} catch (_) {
var _error = _;
var _hasError = true;
_usingCtx.e = _;
} finally {
await babelHelpers.dispose(_stack, _error, _hasError);
await _usingCtx.dispose();
}
@@ -1,13 +1,12 @@
try {
var _stack = [];
const x = babelHelpers.using(_stack, obj, true);
var _usingCtx = babelHelpers.usingCtx();
const x = _usingCtx.using(obj, true);
stmt;
const y = babelHelpers.using(_stack, obj, true),
z = babelHelpers.using(_stack, obj, true);
const y = _usingCtx.using(obj, true),
z = _usingCtx.using(obj, true);
doSomethingWith(x, y);
} catch (_) {
var _error = _;
var _hasError = true;
_usingCtx.e = _;
} finally {
await babelHelpers.dispose(_stack, _error, _hasError);
await _usingCtx.dispose();
}
@@ -1,10 +1,9 @@
try {
var _stack = [];
const x = babelHelpers.using(_stack, obj);
var _usingCtx = babelHelpers.usingCtx();
const x = _usingCtx.using(obj);
doSomethingWith(x);
} catch (_) {
var _error = _;
var _hasError = true;
_usingCtx.e = _;
} finally {
babelHelpers.dispose(_stack, _error, _hasError);
_usingCtx.dispose();
}
@@ -1,10 +1,9 @@
for await (const _x of y) try {
var _stack = [];
const x = babelHelpers.using(_stack, _x);
var _usingCtx = babelHelpers.usingCtx();
const x = _usingCtx.using(_x);
doSomethingWith(x);
} catch (_) {
var _error = _;
var _hasError = true;
_usingCtx.e = _;
} finally {
babelHelpers.dispose(_stack, _error, _hasError);
_usingCtx.dispose();
}
@@ -1,10 +1,9 @@
for (const _x of y) try {
var _stack = [];
const x = babelHelpers.using(_stack, _x);
var _usingCtx = babelHelpers.usingCtx();
const x = _usingCtx.using(_x);
doSomethingWith(x);
} catch (_) {
var _error = _;
var _hasError = true;
_usingCtx.e = _;
} finally {
babelHelpers.dispose(_stack, _error, _hasError);
_usingCtx.dispose();
}
@@ -1,12 +1,11 @@
function fn() {
try {
var _stack = [];
const x = babelHelpers.using(_stack, obj);
var _usingCtx = babelHelpers.usingCtx();
const x = _usingCtx.using(obj);
return doSomethingWith(x);
} catch (_) {
var _error = _;
var _hasError = true;
_usingCtx.e = _;
} finally {
babelHelpers.dispose(_stack, _error, _hasError);
_usingCtx.dispose();
}
}
@@ -1,10 +1,9 @@
if (test) try {
var _stack = [];
const x = babelHelpers.using(_stack, obj);
var _usingCtx = babelHelpers.usingCtx();
const x = _usingCtx.using(obj);
doSomethingWith(x);
} catch (_) {
var _error = _;
var _hasError = true;
_usingCtx.e = _;
} finally {
babelHelpers.dispose(_stack, _error, _hasError);
_usingCtx.dispose();
}

0 comments on commit 376555f

Please sign in to comment.