Skip to content

Commit ec717ab

Browse files
committed
fix: use call_super location
1 parent 50d3f54 commit ec717ab

File tree

5 files changed

+171
-19
lines changed

5 files changed

+171
-19
lines changed

test-app/app/src/main/assets/internal/ts_helpers.js

+1-6
Original file line numberDiff line numberDiff line change
@@ -63,11 +63,7 @@
6363
if (Parent.__isPrototypeImplementationObject) {
6464
throw new Error("Can not extend an already extended native object.");
6565
}
66-
67-
let error = new Error("");
68-
69-
console.log(error.stack.split("\n")[2]);
70-
66+
7167
function extend(thiz) {
7268
var child = thiz.__proto__.__child;
7369
if (!child.__extended) {
@@ -77,7 +73,6 @@
7773
child[Symbol.hasInstance] = function (instance) {
7874
return instance instanceof this.__extended;
7975
};
80-
error = null;
8176
}
8277
return child.__extended;
8378
}

test-app/build-tools/jsparser/visitors/es5-visitors.js

+159-11
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,10 @@ var es5_visitors = (function () {
118118
var overriddenMethodNames = _getOverriddenMethodsTypescript(path, 3);
119119

120120
var declaredClassName = "";
121+
var extendPath = _getParent(path, 3, config);
122+
const location = getTypeScriptExtendSuperCallLocation(extendPath, config);
123+
const line = location.line
124+
const column = location.column;
121125

122126
var extendParent = _getParent(path, 1, config);
123127

@@ -189,8 +193,8 @@ var es5_visitors = (function () {
189193
overriddenMethodNames,
190194
{
191195
file: config.filePath,
192-
line: path.node.loc.end.line,
193-
column: path.node.loc.start.column + 1,
196+
line: line,
197+
column: column + 1,
194198
className: declaredClassName,
195199
},
196200
"",
@@ -236,15 +240,10 @@ var es5_visitors = (function () {
236240
}
237241
}
238242

239-
console.log(extendClass);
240-
241-
/**
242-
* Get _inherits._ property location or _inherits function location.
243-
*/
244-
const location =
245-
defaultDepth === 5 ? path.container.loc : path.container.property.loc;
246-
const line = location.start.line;
247-
const column = location.start.column;
243+
var extendPath = _getParent(path, defaultDepth - 2, config);
244+
const location = getTypeScriptExtendSuperCallLocation(extendPath, config);
245+
const line = location.line
246+
const column = location.column;
248247

249248
var overriddenMethodNames = [];
250249

@@ -652,6 +651,155 @@ var es5_visitors = (function () {
652651
/*
653652
* HELPER METHODS
654653
*/
654+
655+
656+
function getTypeScriptExtendSuperCallLocation(extendPath, config) {
657+
var constructorFunctionName;
658+
var returnIdentifierName;
659+
var superCalleeStartColumn;
660+
var superCalleeLine;
661+
var locationAssigned = false;
662+
663+
664+
// checks if constructor function and return identifiers match in a transpiled typescript class extend
665+
if (extendPath.node.body && extendPath.node.body.length >= 3) {
666+
if (types.isFunctionDeclaration(extendPath.node.body[1]) && extendPath.node.body[1].id)
667+
constructorFunctionName = extendPath.node.body[1].id.name;
668+
if (types.isReturnStatement(extendPath.node.body[extendPath.node.body.length - 1]))
669+
returnIdentifierName = extendPath.node.body[extendPath.node.body.length - 1].argument.name;
670+
}
671+
672+
673+
674+
675+
// checks the typescript-extended class for a strict format, and a super call/apply inside
676+
/**
677+
* function MyBtn() {
678+
var _this = _super.call(this) || this;
679+
return global.__native(_this);
680+
}
681+
682+
**UGLIFIED extended class**
683+
684+
function t(t) {
685+
var r = e.call(this) || this;
686+
r.textBase = t;
687+
return global.__native(r);
688+
}
689+
*/
690+
if (constructorFunctionName === returnIdentifierName && !!constructorFunctionName) {
691+
var constructorFunctionScope = extendPath.node.body[1];
692+
// the 'super' variable will always be passed as the second argument to the __extends call
693+
// try to find the 'super' identifier which may be uglified
694+
var superVariableIdentifier = getSuperVariableIdentifier(extendPath.node.body[0]);
695+
696+
697+
//// helper functions to find the correct super.call(this) node
698+
function getSuperVariableIdentifier(__extendsNode) {
699+
if (types.isExpressionStatement(__extendsNode) && types.isCallExpression(__extendsNode.expression)) {
700+
var __extendsCallArguments = __extendsNode.expression.arguments;
701+
if (__extendsCallArguments.length == 2) {
702+
return __extendsCallArguments[1].name;
703+
}
704+
}
705+
}
706+
707+
/** Getting the super.call node from assignment
708+
if expressionStatement => check possibleExpressionStatements[0]
709+
if possibleExpressionStatements[0].expression is assignment expression
710+
if possibleExpressionStatements[0].expression.right is logical expression
711+
if possibleExpressionStatements[0].expression.right.left is Call expression
712+
if possibleExpressionStatements[0].expression.right.left.callee.object.name === superVariableIdentifier
713+
if the above is valid, then variableRHS = possibleVariableDeclarations[0].expression.right.left
714+
*/
715+
function getThisAssignmentSuperCallLineNode(nodes, superIdentifier) {
716+
var matchingNodes = nodes.filter(
717+
(node) => {
718+
719+
if (types.isMemberExpression(node.expression?.right?.callee?.expressions[1])
720+
&& node.expression?.right?.callee?.expressions[1].object.name.includes("call_super")) return true;
721+
722+
return types.isAssignmentExpression(node.expression) &&
723+
types.isLogicalExpression(node.expression.right) &&
724+
types.isCallExpression(node.expression.right.left) &&
725+
(node.expression.right.left.callee.object.name === superIdentifier ||
726+
node.expression.right.left.callee.object.name.includes("call_super")
727+
)
728+
});
729+
730+
731+
if (matchingNodes.length > 0 &&
732+
types.isMemberExpression(matchingNodes[0].expression?.right?.callee?.expressions[1])
733+
&& matchingNodes[0].expression?.right?.callee?.expressions[1].object.name.includes("call_super"))
734+
{
735+
return matchingNodes[0].expression?.right?.callee?.expressions[1];
736+
}
737+
738+
return matchingNodes.length > 0 ? matchingNodes[0].expression?.right?.left : null;
739+
}
740+
741+
/** Getting the super.call node from declaration
742+
if variableDeclaration => check possibleVariableDeclarations[0].declarations[0].init isn't null
743+
if possibleNodesForSuperCall[0].declarations[0].init is logical expression
744+
if possibleNodesForSuperCall[0].declarations[0].init.left is Call Expression
745+
if possibleNodesForSuperCall[0].declarations[0].init.left.callee.object.name === superVariableIdentifier
746+
if the above is valid, then variableRHS = possibleVariableDeclarations[0].declarations[0].init.left
747+
*/
748+
function getThisDeclarationSuperCallLineNode(nodes, superIdentifier) {
749+
var matchingNodes = nodes.filter(
750+
(node) => {
751+
return types.isLogicalExpression(node.declarations[0].init) &&
752+
types.isCallExpression(node.declarations[0].init.left) &&
753+
node.declarations[0].init.left.callee.object.name === superIdentifier;
754+
});
755+
756+
return matchingNodes.length > 0 ? matchingNodes[0].declarations[0].init.left : null;
757+
}
758+
////
759+
760+
if (superVariableIdentifier) {
761+
var possibleVariableDeclarations = [];
762+
var possibleExpressionStatements = [];
763+
764+
constructorFunctionScope.body.body.forEach(node => {
765+
if (types.isVariableDeclaration(node)) {
766+
possibleVariableDeclarations.push(node);
767+
} else if (types.isExpressionStatement(node)) {
768+
possibleExpressionStatements.push(node);
769+
}
770+
});
771+
772+
if (possibleVariableDeclarations.length > 0 || possibleExpressionStatements.length > 0) {
773+
var superCallRHS = getThisDeclarationSuperCallLineNode(possibleVariableDeclarations, superVariableIdentifier) ||
774+
getThisAssignmentSuperCallLineNode(possibleExpressionStatements, superVariableIdentifier);
775+
776+
if (types.isMemberExpression(superCallRHS)) {
777+
var superCallee = superCallRHS.property;
778+
superCalleeStartColumn = superCallee.loc.start.column + 2;
779+
superCalleeLine = superCallee.loc.start.line;
780+
locationAssigned = true;
781+
} else if (superCallRHS) {
782+
var superCallee = superCallRHS.callee.property;
783+
superCalleeStartColumn = superCallee.loc.start.column + 1;
784+
superCalleeLine = superCallee.loc.start.line;
785+
786+
locationAssigned = true;
787+
}
788+
}
789+
}
790+
}
791+
792+
if (!locationAssigned) {
793+
config.logger.info(UNSUPPORTED_TYPESCRIPT_EXTEND_FORMAT_MESSAGE + " ctor function name: " + constructorFunctionName);
794+
}
795+
796+
return {
797+
line: superCalleeLine,
798+
column: superCalleeStartColumn
799+
};
800+
}
801+
802+
655803
function _getOverriddenMethods(node, config) {
656804
var overriddenMethodNames = [];
657805
if (types.isObjectExpression(node)) {

test-app/runtime/src/main/cpp/runtime/metadata/MetadataNode.cpp

+6-2
Original file line numberDiff line numberDiff line change
@@ -507,10 +507,14 @@ bool
507507
MetadataNode::GetExtendLocation(napi_env env, string &extendLocation, bool isTypeScriptExtend) {
508508
stringstream extendLocationStream;
509509

510-
auto frames = tns::BuildStacktraceFrames(env, nullptr, 3);
510+
auto frames = tns::BuildStacktraceFrames(env, nullptr, 4);
511511
tns::JsStacktraceFrame *frame;
512512
if (isTypeScriptExtend) {
513-
frame = &frames[2]; // the _super.apply call to ts_helpers will always be the third call frame
513+
if (Util::Contains(frames[2].text, "call_super")) {
514+
frame = &frames[3];
515+
} else {
516+
frame = &frames[2]; // the _super.apply call to ts_helpers will always be the third call frame
517+
}
514518
} else {
515519
frame = &frames[0];
516520
}

test-app/runtime/src/main/cpp/runtime/util/Util.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,10 @@ namespace tns {
7979
return res;
8080
}
8181

82+
bool Util::Contains(const string &str, const string &sequence) {
83+
return str.find(sequence) != string::npos;
84+
}
85+
8286
string Util::ConvertFromJniToCanonicalName(const string &name) {
8387
string converted = name;
8488
replace(converted.begin(), converted.end(), '/', '.');

test-app/runtime/src/main/cpp/runtime/util/Util.h

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ class Util {
1717
static void JoinString(const std::vector<std::string>& list, const std::string& delimiter, std::string& out);
1818

1919
static bool EndsWith(const std::string& str, const std::string& suffix);
20+
static bool Contains(const std::string &str, const std::string &sequence);
2021

2122
static std::string ConvertFromJniToCanonicalName(const std::string& name);
2223

0 commit comments

Comments
 (0)