"this" in evaluated javascript is not correct
Closed this issue · 14 comments
e.g. I have this code snippet:
var functions = {
func: function() {
eval("this.style.height");
}.bind(document.documentElement)
}
If I instrument it with the latest JSCover version, I get this:
_$jscoverage['/index.js'].lineData[1]++;
var functions = {func:function() {
_$jscoverage['/index.js'].functionData[0]++;
_$jscoverage['/index.js'].lineData[3]++;
(0,eval)('this.style.height');
}.bind(document.documentElement)};
Unfortunately this.style.height triggers the script error "Cannot read property 'height' of undefined"
I think this is a closure compiler bug. I'll have to dig in to replicate using the command line and raise it there.
Hmmm java -jar ~/.m2/repository/com/google/javascript/closure-compiler/v20180402/closure-compiler-v20180402.jar --js test.js --language_in ECMASCRIPT_2017 --language_out ECMASCRIPT_2017 --formatting PRETTY_PRINT
seems to work OK. Will have to debug to see what's the difference in print and/or parser options.
Comparing closure-compile config internals which work (1st line) with JSCover parser's which doesn't (2nd).
CompilerOptions{aggressiveFusion=false, aliasableStrings=[], aliasAllStrings=false, aliasHandler=com.google.javascript.jscomp.CompilerOptions$NullAliasTransformationHandler@2ea227af, aliasStringsBlacklist=, allowHotswapReplaceScript=false, ambiguateProperties=false, angularPass=false, anonymousFunctionNaming=OFF, appNameStr=, assumeClosuresOnlyCaptureReferences=false, assumeStrictThis=false, brokenClosureRequiresLevel=ERROR, checkDeterminism=false, checkGlobalNamesLevel=OFF, checkGlobalThisLevel=OFF, checkMissingGetCssNameLevel=OFF, checksOnly=false, checkSuspiciousCode=true, checkSymbols=false, checkTypes=false, closurePass=true, coalesceVariableNames=true, codingConvention=com.google.javascript.jscomp.ClosureCodingConvention@7e7be63f, collapseAnonymousFunctions=false, collapseObjectLiterals=true, collapseProperties=NONE, collapseVariableDeclarations=true, colorizeErrorOutput=false, computeFunctionSideEffects=false, conformanceConfigs=[], continueAfterErrors=false, convertToDottedProperties=true, crossModuleCodeMotion=false, crossModuleCodeMotionNoStubMethods=false, crossModuleMethodMotion=false, dartPass=false, deadAssignmentElimination=true, declaredGlobalExternsOnWindow=true, defineReplacements={}, dependencyOptions=DependencyOptions{sortDependencies=true, pruneDependencies=false, dropMoochers=false, entryPoints=[]}, devirtualizePrototypeMethods=false, devMode=OFF, disambiguatePrivateProperties=false, disambiguateProperties=false, enforceAccessControlCodingConventions=false, environment=BROWSER, errorFormat=SINGLELINE, exportLocalPropertyDefinitions=false, exportTestFunctions=false, externExports=false, extraAnnotationNames=[], extractPrototypeMemberDeclarations=OFF, extraSmartNameRemoval=false, filesToPrintAfterEachPassRegexList=[], flowSensitiveInlineVariables=false, foldConstants=true, forceLibraryInjection=[], gatherCssNames=false, generateExportsAfterTypeChecking=true, generateExports=false, generatePseudoNames=false, generateTypedExterns=false, idGenerators={}, incrementalCheckMode=OFF, inferConsts=true, inferTypes=false, inlineConstantVars=false, inlineFunctionsLevel=LOCAL_ONLY, inlineGetters=false, inlineLocalVariables=true, inlineProperties=false, inlineVariables=false, inputDelimiter=// Input %num%, inputSourceMaps={}, instrumentationTemplateFile=, instrumentForCoverage=false, instrumentForCoverageOnly=false, instrumentBranchCoverage=false, j2clPassMode=AUTO, labelRenaming=true, languageIn=ECMASCRIPT_2017, languageOut=ECMASCRIPT_2017, legacyCodeCompile=false, lineBreak=false, lineLengthThreshold=500, markAsCompiled=false, markNoSideEffectCalls=false, maxFunctionSizeAfterInlining=-1, moduleRoots=[], modulesToPrintAfterEachPassRegexList=[], moveFunctionDeclarations=false, nameGenerator=com.google.javascript.jscomp.DefaultNameGenerator@31304f14, optimizeArgumentsArray=true, optimizeCalls=false, outputCharset=US-ASCII, outputJs=NORMAL, outputJsStringUsage=false, parentModuleCanSeeSymbolsDeclaredInChildren=false, parseJsDocDocumentation=TYPES_ONLY, preferLineBreakAtEndOfFile=false, preferSingleQuotes=false, preferStableNames=false, preserveDetailedSourceInfo=false, preserveGoogProvidesAndRequires=false, preserveTypeAnnotations=false, prettyPrint=true, preventLibraryInjection=false, printConfig=false, printInputDelimiter=false, printSourceAfterEachPass=false, processCommonJSModules=false, transpileEs6ModulesToCjsModules=false, processObjectPropertyString=false, propertyInvalidationErrors={}, propertyRenaming=OFF, protectHiddenSideEffects=true, quoteKeywordProperties=false, recordFunctionInformation=false, removeAbstractMethods=false, removeSuperMethods=false, removeClosureAsserts=false, removeJ2clAsserts=true, removeDeadCode=true, removeUnusedClassProperties=false, removeUnusedConstructorProperties=false, removeUnusedLocalVars=true, removeUnusedPrototypePropertiesInExterns=false, removeUnusedPrototypeProperties=false, removeUnusedVars=false, renamePrefixNamespaceAssumeCrossModuleNames=false, replaceIdGenerators=false, replaceMessagesWithChromeI18n=false, replaceStringsFunctionDescriptions=[], replaceStringsPlaceholderToken=, replaceStringsReservedStrings=[], reserveRawExports=false, rewriteFunctionExpressions=false, rewritePolyfills=true, runtimeTypeCheck=false, shadowVariables=true, skipNonTranspilationPasses=false, smartNameRemoval=false, sourceMapDetailLevel=ALL, sourceMapFormat=DEFAULT, sourceMapLocationMappings=[], stripNamePrefixes=[], stripNameSuffixes=[], stripTypePrefixes=[], stripTypes=[], summaryDetailLevel=1, tracer=OFF, transformAMDToCJSModules=false, trustedStrings=true, tweakProcessing=OFF, tweakReplacements={}, emitUseStrict=Optional.absent(), useTypesForLocalOptimization=false, variableRenaming=LOCAL, warningsGuard=DiagnosticGroup<checkVars>(OFF), DiagnosticGroup<es5Strict>(ERROR), com.google.javascript.jscomp.DiagnosticGroup@6f15d60e(OFF), DiagnosticGroup<nonStandardJsDocs>(OFF), wrapGoogModulesForWhitespaceOnly=true}
CompilerOptions{aggressiveFusion=false, aliasableStrings=[], aliasAllStrings=false, aliasHandler=com.google.javascript.jscomp.CompilerOptions$NullAliasTransformationHandler@7e0a8eeb, aliasStringsBlacklist=, allowHotswapReplaceScript=false, ambiguateProperties=false, angularPass=false, anonymousFunctionNaming=OFF, appNameStr=, assumeClosuresOnlyCaptureReferences=false, assumeStrictThis=false, brokenClosureRequiresLevel=ERROR, checkDeterminism=false, checkGlobalNamesLevel=OFF, checkGlobalThisLevel=OFF, checkMissingGetCssNameLevel=OFF, checksOnly=false, checkSuspiciousCode=false, checkSymbols=false, checkTypes=false, closurePass=true, coalesceVariableNames=true, codingConvention=com.google.javascript.jscomp.ClosureCodingConvention@70f69ac5, collapseAnonymousFunctions=false, collapseObjectLiterals=true, collapseProperties=NONE, collapseVariableDeclarations=true, colorizeErrorOutput=false, computeFunctionSideEffects=false, conformanceConfigs=[], continueAfterErrors=false, convertToDottedProperties=true, crossModuleCodeMotion=false, crossModuleCodeMotionNoStubMethods=false, crossModuleMethodMotion=false, dartPass=false, deadAssignmentElimination=true, declaredGlobalExternsOnWindow=true, defineReplacements={}, dependencyOptions=DependencyOptions{sortDependencies=true, pruneDependencies=false, dropMoochers=false, entryPoints=[]}, devirtualizePrototypeMethods=false, devMode=OFF, disambiguatePrivateProperties=false, disambiguateProperties=false, enforceAccessControlCodingConventions=false, environment=BROWSER, errorFormat=SINGLELINE, exportLocalPropertyDefinitions=false, exportTestFunctions=false, externExports=false, extractPrototypeMemberDeclarations=OFF, extraSmartNameRemoval=false, filesToPrintAfterEachPassRegexList=[], flowSensitiveInlineVariables=false, foldConstants=true, forceLibraryInjection=[], gatherCssNames=false, generateExportsAfterTypeChecking=true, generateExports=false, generatePseudoNames=false, generateTypedExterns=false, idGenerators={}, incrementalCheckMode=OFF, inferConsts=true, inferTypes=false, inlineConstantVars=false, inlineFunctionsLevel=LOCAL_ONLY, inlineGetters=false, inlineLocalVariables=true, inlineProperties=false, inlineVariables=false, inputDelimiter=// Input %num%, inputSourceMaps={}, instrumentationTemplateFile=, instrumentForCoverage=false, instrumentForCoverageOnly=false, instrumentBranchCoverage=false, j2clPassMode=AUTO, labelRenaming=true, languageIn=ECMASCRIPT_2017, languageOut=ECMASCRIPT_2017, legacyCodeCompile=false, lineBreak=false, lineLengthThreshold=500, markAsCompiled=false, markNoSideEffectCalls=false, maxFunctionSizeAfterInlining=-1, moduleRoots=[./], modulesToPrintAfterEachPassRegexList=[], moveFunctionDeclarations=false, nameGenerator=com.google.javascript.jscomp.DefaultNameGenerator@10096f5d, optimizeArgumentsArray=true, optimizeCalls=false, outputJs=NORMAL, outputJsStringUsage=false, parentModuleCanSeeSymbolsDeclaredInChildren=false, parseJsDocDocumentation=TYPES_ONLY, preferLineBreakAtEndOfFile=false, preferSingleQuotes=true, preferStableNames=false, preserveDetailedSourceInfo=false, preserveGoogProvidesAndRequires=false, preserveTypeAnnotations=false, prettyPrint=true, preventLibraryInjection=false, printConfig=false, printInputDelimiter=false, printSourceAfterEachPass=false, processCommonJSModules=false, transpileEs6ModulesToCjsModules=false, processObjectPropertyString=false, propertyInvalidationErrors={}, propertyRenaming=OFF, protectHiddenSideEffects=true, quoteKeywordProperties=false, recordFunctionInformation=false, removeAbstractMethods=false, removeSuperMethods=false, removeClosureAsserts=false, removeJ2clAsserts=true, removeDeadCode=true, removeUnusedClassProperties=false, removeUnusedConstructorProperties=false, removeUnusedLocalVars=true, removeUnusedPrototypePropertiesInExterns=false, removeUnusedPrototypeProperties=false, removeUnusedVars=false, renamePrefixNamespaceAssumeCrossModuleNames=false, replaceIdGenerators=false, replaceMessagesWithChromeI18n=false, replaceStringsFunctionDescriptions=[], replaceStringsPlaceholderToken=, replaceStringsReservedStrings=[], reserveRawExports=false, rewriteFunctionExpressions=false, rewritePolyfills=false, runtimeTypeCheck=false, shadowVariables=true, skipNonTranspilationPasses=false, smartNameRemoval=false, sourceMapDetailLevel=ALL, sourceMapFormat=DEFAULT, sourceMapLocationMappings=[], stripNamePrefixes=[], stripNameSuffixes=[], stripTypePrefixes=[], stripTypes=[], summaryDetailLevel=1, tracer=OFF, transformAMDToCJSModules=false, trustedStrings=true, tweakProcessing=OFF, tweakReplacements={}, emitUseStrict=Optional.absent(), useTypesForLocalOptimization=false, variableRenaming=LOCAL, warningsGuard=, wrapGoogModulesForWhitespaceOnly=true}
Config{languageMode=ECMASCRIPT8, strictMode=STRICT, jsDocParsingMode=TYPES_ONLY, runMode=STOP_AFTER_ERROR, annotations={ngInject=NG_INJECT, abstract=ABSTRACT, argument=PARAM, author=AUTHOR, consistentIdGenerator=CONSISTENTIDGENERATOR, const=CONSTANT, constant=CONSTANT, constructor=CONSTRUCTOR, customElement=CUSTOM_ELEMENT, copyright=LICENSE, define=DEFINE, deprecated=DEPRECATED, desc=DESC, dict=DICT, disposes=DISPOSES, enum=ENUM, export=EXPORT, expose=EXPOSE, extends=EXTENDS, externs=EXTERNS, fileoverview=FILE_OVERVIEW, final=FINAL, hidden=HIDDEN, idGenerator=IDGENERATOR, implements=IMPLEMENTS, implicitCast=IMPLICIT_CAST, inheritDoc=INHERIT_DOC, interface=INTERFACE, record=RECORD, lends=LENDS, license=LICENSE, meaning=MEANING, mixinClass=MIXIN_CLASS, mixinFunction=MIXIN_FUNCTION, modifies=MODIFIES, nocollapse=NO_COLLAPSE, nocompile=NO_COMPILE, noinline=NO_INLINE, nosideeffects=NO_SIDE_EFFECTS, override=OVERRIDE, owner=AUTHOR, package=PACKAGE, param=PARAM, polymer=POLYMER, polymerBehavior=POLYMER_BEHAVIOR, preserve=PRESERVE, private=PRIVATE, protected=PROTECTED, public=PUBLIC, return=RETURN, returns=RETURN, see=SEE, stableIdGenerator=STABLEIDGENERATOR, struct=STRUCT, suppress=SUPPRESS, template=TEMPLATE, this=THIS, throws=THROWS, type=TYPE, typedef=TYPEDEF, typeSummary=TYPE_SUMMARY, unrestricted=UNRESTRICTED, version=VERSION, wizaction=WIZACTION, exception=NOT_IMPLEMENTED, hassoydelcall=NOT_IMPLEMENTED, parent=NOT_IMPLEMENTED, usage=NOT_IMPLEMENTED, channel=NOT_IMPLEMENTED, methodOf=NOT_IMPLEMENTED, readonly=NOT_IMPLEMENTED, borrows=NOT_IMPLEMENTED, property=NOT_IMPLEMENTED, docsNotRequired=NOT_IMPLEMENTED, model=NOT_IMPLEMENTED, id=NOT_IMPLEMENTED, multiElement=NOT_IMPLEMENTED, element=NOT_IMPLEMENTED, method=NOT_IMPLEMENTED, module=NOT_IMPLEMENTED, eventType=NOT_IMPLEMENTED, priority=NOT_IMPLEMENTED, codepen=NOT_IMPLEMENTED, fires=NOT_IMPLEMENTED, field=NOT_IMPLEMENTED, preserveTry=NOT_IMPLEMENTED, mixes=NOT_IMPLEMENTED, requires=NOT_IMPLEMENTED, propertyOf=NOT_IMPLEMENTED, global=NOT_IMPLEMENTED, hassoydeltemplate=NOT_IMPLEMENTED, restrict=NOT_IMPLEMENTED, example=NOT_IMPLEMENTED, delegate=NOT_IMPLEMENTED, default=NOT_IMPLEMENTED, file=NOT_IMPLEMENTED, member=NOT_IMPLEMENTED, memberOf=NOT_IMPLEMENTED, event=NOT_IMPLEMENTED, url=NOT_IMPLEMENTED, todo=NOT_IMPLEMENTED, bug=NOT_IMPLEMENTED, docs-private=NOT_IMPLEMENTED, classdesc=NOT_IMPLEMENTED, wizmodule=NOT_IMPLEMENTED, config=NOT_IMPLEMENTED, augments=NOT_IMPLEMENTED, supported=NOT_IMPLEMENTED, wizSupportsSymbolicLookup=NOT_IMPLEMENTED, pintomodule=NOT_IMPLEMENTED, exportInterface=NOT_IMPLEMENTED, mods=NOT_IMPLEMENTED, instance=NOT_IMPLEMENTED, enhanceable=NOT_IMPLEMENTED, requirecss=NOT_IMPLEMENTED, function=NOT_IMPLEMENTED, static=NOT_IMPLEMENTED, visibility=NOT_IMPLEMENTED, kind=NOT_IMPLEMENTED, inner=NOT_IMPLEMENTED, mixin=NOT_IMPLEMENTED, name=NOT_IMPLEMENTED, modName=NOT_IMPLEMENTED, memberof=NOT_IMPLEMENTED, exec=NOT_IMPLEMENTED, since=NOT_IMPLEMENTED, virtual=NOT_IMPLEMENTED, addon=NOT_IMPLEMENTED, exportDoc=NOT_IMPLEMENTED, link=NOT_IMPLEMENTED, description=NOT_IMPLEMENTED, constructs=NOT_IMPLEMENTED, demo=NOT_IMPLEMENTED, noalias=NOT_IMPLEMENTED, animations=NOT_IMPLEMENTED, scope=NOT_IMPLEMENTED, alias=NOT_IMPLEMENTED, ignore=NOT_IMPLEMENTED, tutorial=NOT_IMPLEMENTED, class=NOT_IMPLEMENTED, enhance=NOT_IMPLEMENTED, summary=NOT_IMPLEMENTED, ngdoc=NOT_IMPLEMENTED, eventOf=NOT_IMPLEMENTED, namespace=NOT_IMPLEMENTED, provideGoog=NOT_IMPLEMENTED, base=NOT_IMPLEMENTED}, suppressionNames=[accessControls, ambiguousFunctionDecl, checkDebuggerStatement, checkEventfulObjectDisposal, checkRegExp, checkTypes, checkVars, closureDepMethodUsageChecks, const, constantProperty, deprecated, duplicate, es5Strict, externsValidation, extraProvide, extraRequire, fileoverviewTags, globalThis, invalidCasts, legacyGoogScopeRequire, lateProvide, lintChecks, messageConventions, misplacedTypeAnnotation, missingOverride, missingPolyfill, missingProperties, missingProvide, missingRequire, missingReturn, moduleLoad, newCheckTypes, newCheckTypesAllChecks, nonStandardJsDocs, reportUnknownTypes, strictCheckTypes, strictMissingProperties, strictModuleDepCheck, strictPrimitiveOperators, suspiciousCode, transitionalSuspiciousCodeWarnings, undefinedNames, undefinedVars, underscore, unknownDefines, unusedLocalVariables, unusedPrivateMembers, uselessCode, visibility, with], parseInlineSourceMaps=true}
Config{languageMode=ECMASCRIPT8, strictMode=SLOPPY, jsDocParsingMode=INCLUDE_DESCRIPTIONS_WITH_WHITESPACE, runMode=KEEP_GOING, annotations={ngInject=NG_INJECT, abstract=ABSTRACT, argument=PARAM, author=AUTHOR, consistentIdGenerator=CONSISTENTIDGENERATOR, const=CONSTANT, constant=CONSTANT, constructor=CONSTRUCTOR, customElement=CUSTOM_ELEMENT, copyright=LICENSE, define=DEFINE, deprecated=DEPRECATED, desc=DESC, dict=DICT, disposes=DISPOSES, enum=ENUM, export=EXPORT, expose=EXPOSE, extends=EXTENDS, externs=EXTERNS, fileoverview=FILE_OVERVIEW, final=FINAL, hidden=HIDDEN, idGenerator=IDGENERATOR, implements=IMPLEMENTS, implicitCast=IMPLICIT_CAST, inheritDoc=INHERIT_DOC, interface=INTERFACE, record=RECORD, lends=LENDS, license=LICENSE, meaning=MEANING, mixinClass=MIXIN_CLASS, mixinFunction=MIXIN_FUNCTION, modifies=MODIFIES, nocollapse=NO_COLLAPSE, nocompile=NO_COMPILE, noinline=NO_INLINE, nosideeffects=NO_SIDE_EFFECTS, override=OVERRIDE, owner=AUTHOR, package=PACKAGE, param=PARAM, polymer=POLYMER, polymerBehavior=POLYMER_BEHAVIOR, preserve=PRESERVE, private=PRIVATE, protected=PROTECTED, public=PUBLIC, return=RETURN, returns=RETURN, see=SEE, stableIdGenerator=STABLEIDGENERATOR, struct=STRUCT, suppress=SUPPRESS, template=TEMPLATE, this=THIS, throws=THROWS, type=TYPE, typedef=TYPEDEF, typeSummary=TYPE_SUMMARY, unrestricted=UNRESTRICTED, version=VERSION, wizaction=WIZACTION, addon=NOT_IMPLEMENTED, alias=NOT_IMPLEMENTED, animations=NOT_IMPLEMENTED, augments=NOT_IMPLEMENTED, base=NOT_IMPLEMENTED, borrows=NOT_IMPLEMENTED, bug=NOT_IMPLEMENTED, channel=NOT_IMPLEMENTED, class=NOT_IMPLEMENTED, classdesc=NOT_IMPLEMENTED, codepen=NOT_IMPLEMENTED, config=NOT_IMPLEMENTED, constructs=NOT_IMPLEMENTED, default=NOT_IMPLEMENTED, delegate=NOT_IMPLEMENTED, demo=NOT_IMPLEMENTED, description=NOT_IMPLEMENTED, docsNotRequired=NOT_IMPLEMENTED, docs-private=NOT_IMPLEMENTED, element=NOT_IMPLEMENTED, enhance=NOT_IMPLEMENTED, enhanceable=NOT_IMPLEMENTED, event=NOT_IMPLEMENTED, eventOf=NOT_IMPLEMENTED, eventType=NOT_IMPLEMENTED, example=NOT_IMPLEMENTED, exception=NOT_IMPLEMENTED, exec=NOT_IMPLEMENTED, exportDoc=NOT_IMPLEMENTED, exportInterface=NOT_IMPLEMENTED, field=NOT_IMPLEMENTED, file=NOT_IMPLEMENTED, fires=NOT_IMPLEMENTED, function=NOT_IMPLEMENTED, global=NOT_IMPLEMENTED, hassoydelcall=NOT_IMPLEMENTED, hassoydeltemplate=NOT_IMPLEMENTED, id=NOT_IMPLEMENTED, ignore=NOT_IMPLEMENTED, inner=NOT_IMPLEMENTED, instance=NOT_IMPLEMENTED, kind=NOT_IMPLEMENTED, link=NOT_IMPLEMENTED, member=NOT_IMPLEMENTED, memberOf=NOT_IMPLEMENTED, memberof=NOT_IMPLEMENTED, method=NOT_IMPLEMENTED, methodOf=NOT_IMPLEMENTED, mixes=NOT_IMPLEMENTED, mixin=NOT_IMPLEMENTED, modName=NOT_IMPLEMENTED, model=NOT_IMPLEMENTED, mods=NOT_IMPLEMENTED, module=NOT_IMPLEMENTED, multiElement=NOT_IMPLEMENTED, name=NOT_IMPLEMENTED, namespace=NOT_IMPLEMENTED, ngdoc=NOT_IMPLEMENTED, noalias=NOT_IMPLEMENTED, parent=NOT_IMPLEMENTED, pintomodule=NOT_IMPLEMENTED, preserveTry=NOT_IMPLEMENTED, priority=NOT_IMPLEMENTED, property=NOT_IMPLEMENTED, propertyOf=NOT_IMPLEMENTED, provideGoog=NOT_IMPLEMENTED, readonly=NOT_IMPLEMENTED, requirecss=NOT_IMPLEMENTED, requires=NOT_IMPLEMENTED, restrict=NOT_IMPLEMENTED, scope=NOT_IMPLEMENTED, since=NOT_IMPLEMENTED, static=NOT_IMPLEMENTED, summary=NOT_IMPLEMENTED, supported=NOT_IMPLEMENTED, todo=NOT_IMPLEMENTED, tutorial=NOT_IMPLEMENTED, url=NOT_IMPLEMENTED, usage=NOT_IMPLEMENTED, virtual=NOT_IMPLEMENTED, visibility=NOT_IMPLEMENTED, wizSupportsSymbolicLookup=NOT_IMPLEMENTED, wizmodule=NOT_IMPLEMENTED}, suppressionNames=[accessControls, ambiguousFunctionDecl, checkDebuggerStatement, checkEventfulObjectDisposal, checkRegExp, checkTypes, checkVars, closureDepMethodUsageChecks, const, constantProperty, deprecated, duplicate, es5Strict, externsValidation, extraProvide, extraRequire, fileoverviewTags, globalThis, invalidCasts, legacyGoogScopeRequire, lateProvide, lintChecks, messageConventions, misplacedTypeAnnotation, missingOverride, missingPolyfill, missingProperties, missingProvide, missingRequire, missingReturn, moduleLoad, newCheckTypes, newCheckTypesAllChecks, nonStandardJsDocs, reportUnknownTypes, strictCheckTypes, strictMissingProperties, strictModuleDepCheck, strictPrimitiveOperators, suspiciousCode, transitionalSuspiciousCodeWarnings, undefinedNames, undefinedVars, underscore, unknownDefines, unusedLocalVariables, unusedPrivateMembers, uselessCode, visibility, with], parseInlineSourceMaps=false}
Hmmm. Still investigating. Here's what's in the patch and what I've tried with debugging:
- Removed all instrumenting code from JSCover
- Verify AST for modified JSCover and closure-compiler CLI is the same after parsing (via
Node.toStringTree()
) - Verified all
CodeGenerator
options are the same before printing
What I've noticed that is different is that several external modules are loaded in the colsure-compiler CLI parser.
Hello ! I'm facing the same issue using the last JSCover version (2.0.12). Can you give a status about this issue ? What is the last working version of JSCover ?
I just tested with closure-compiler v20211006, and still have the issue. I'll have to have another look into this. Version 2.0.12 is currently the latest version of JSCover.
The code @kaljak gave should be sufficient to reproduce. (0,eval)
is not equivalent to eval
especially for evaluating this
(cf. https://stackoverflow.com/questions/9107240/1-evalthis-vs-evalthis-in-javascript) so final result is an error.
As soon as I use a JS code generator, these eval('this')
appear really often in the instrumented code. I'm trying to find a closure-compiler CompilerOptions flag for this, but documentation is such a mess...
Edit : I confirm that using closure-compiler comand line eval
is not substituted with (0,eval)
Working AST
jsRoot.toStringTree():
SCRIPT 1:0 [length: 106] [source_file: test.js] [feature_set: []]
VAR 1:0 [length: 106] [source_file: test.js]
NAME functions 1:4 [length: 102] [source_file: test.js]
OBJECTLIT 1:16 [length: 90] [source_file: test.js]
STRING_KEY func 2:2 [length: 4] [source_file: test.js]
CALL 2:8 [length: 78] [source_file: test.js]
GETPROP bind 4:4 [length: 4] [source_file: test.js]
FUNCTION 2:8 [length: 47] [source_file: test.js]
NAME 2:8 [length: 47] [source_file: test.js]
PARAM_LIST 2:16 [length: 2] [source_file: test.js]
BLOCK 2:19 [length: 36] [source_file: test.js]
EXPR_RESULT 3:4 [length: 26] [source_file: test.js]
CALL 3:4 [length: 25] [source_file: test.js]
NAME eval 3:4 [length: 4] [source_file: test.js]
STRINGLIT this.style.height 3:9 [length: 19] [source_file: test.js]
GETPROP documentElement 4:18 [length: 15] [source_file: test.js]
NAME document 4:9 [length: 8] [source_file: test.js]
Broken AST
SCRIPT 1:0 [length: 106] [source_file: test.js] [input_id: InputId: test.js] [feature_set: []]
VAR 1:0 [length: 106] [source_file: test.js]
NAME functions 1:4 [length: 102] [source_file: test.js] [constant_var_flags: 2]
OBJECTLIT 1:16 [length: 90] [source_file: test.js]
STRING_KEY func 2:2 [length: 4] [source_file: test.js]
CALL 2:8 [length: 78] [source_file: test.js]
GETPROP bind 4:4 [length: 4] [source_file: test.js]
FUNCTION 2:8 [length: 47] [source_file: test.js]
NAME 2:8 [length: 47] [source_file: test.js]
PARAM_LIST 2:16 [length: 2] [source_file: test.js]
BLOCK 2:19 [length: 36] [source_file: test.js]
EXPR_RESULT 3:4 [length: 26] [source_file: test.js]
CALL 3:4 [length: 25] [free_call: 1] [source_file: test.js]
NAME eval 3:4 [length: 4] [direct_eval: 1] [source_file: test.js]
STRINGLIT this.style.height 3:9 [length: 19] [source_file: test.js]
GETPROP documentElement 4:18 [length: 15] [source_file: test.js]
NAME document 4:9 [length: 8] [is_constant_name: 1] [source_file: test.js]
Can sort of fix by changing
protected String instrumentSource(String sourceURI, String source) {
SourceFile sourceFile = SourceFile.fromCode(sourceURI, source);
ParserRunner.ParseResult parsed = parse(source, sourceFile);
Node jsRoot = parsed.ast;
commentsHandler.processComments(parsed.comments);
...to...
protected String instrumentSource(String sourceURI, String source) {
SourceFile sourceFile = SourceFile.fromCode(sourceURI, source);
ErrorManager errorManager = new BlackHoleErrorManager();
com.google.javascript.jscomp.Compiler compiler = new com.google.javascript.jscomp.Compiler(errorManager);
Node jsRoot = compiler.parse(sourceFile);
// commentsHandler.processComments(parsed.comments);
...but then I can't process the comments. I'm not sure how the compiler/parser is altered by this yet.
What I've seen debugging and searching in closure-compiler is that PrepareAst
is never used by JSCover whereas it is by using Compiler
.
PrepareAst
is responsible for detecting if a call to eval is indirect or not in order to be changed to (0,eval)
or not in CodeGenerator
. As in you can see in your AST, it is responsible of the direct_eval: 1
causing eval
not being replaced.
That's why your change make it work.
Yep - I noticed that too. Have you seen a way to turn that off using the ParserRunner?
I haven't searched more since I have to focus on another topic. I'll put some effort on that until next week and give you a status.
Maybe the solution is to use Compiler
and get comments differently ? What is the reason comments are treated differently in JSCover ?
Looks good except for a few things:
- The JavaScript version configuration is ignored
- All tests for the above need to swap to the Compiler language mode
- The error reporter should use the logger (new LoggerErrorManager(logger))
- I'd need to review the branch integration tests which use the old parser code
I've fixed most of the above, but would like to merge your fix so you get the credit for your changes. I'll see if I can merge your commits to a branch, tidy up, then merge to the main branch.