diff --git a/scripts/test-runner.js b/scripts/test-runner.js index 796dfd781..efd80a1ae 100644 --- a/scripts/test-runner.js +++ b/scripts/test-runner.js @@ -507,9 +507,11 @@ function runTest(name, code, options: PrepackOptions, args) { if (code.includes(diagnosticExpectedComment)) { let idx = code.indexOf(diagnosticExpectedComment); let errorCodeString = code.substring(idx + diagnosticExpectedComment.length, code.indexOf("\n", idx)); - let errorCodeSet = new Set(); - expectedDiagnostics.set(severity, errorCodeSet); - errorCodeString.split(",").forEach(errorCode => errorCodeSet.add(errorCode.trim())); + if (errorCodeString.trim() !== "") { + let errorCodeSet = new Set(); + expectedDiagnostics.set(severity, errorCodeSet); + errorCodeString.split(",").forEach(errorCode => errorCodeSet.add(errorCode.trim())); + } options.residual = false; options.errorHandler = getErrorHandlerWithWarningCapture(diagnosticOutput, args.verbose); } diff --git a/src/evaluators/CallExpression.js b/src/evaluators/CallExpression.js index 1fd904dc5..c30ce9ebe 100644 --- a/src/evaluators/CallExpression.js +++ b/src/evaluators/CallExpression.js @@ -21,6 +21,7 @@ import { AbstractObjectValue, ConcreteValue, FunctionValue, + NativeFunctionValue, ObjectValue, Value, } from "../values/index.js"; @@ -266,7 +267,7 @@ function tryToEvaluateCallOrLeaveAsAbstract( let effects; let savedSuppressDiagnostics = realm.suppressDiagnostics; try { - realm.suppressDiagnostics = true; + realm.suppressDiagnostics = !(func instanceof NativeFunctionValue) || func.name !== "__optimize"; effects = realm.evaluateForEffects( () => EvaluateDirectCall(realm, strictCode, env, ref, func, thisValue, ast.arguments, tailCall), undefined, diff --git a/src/serializer/functions.js b/src/serializer/functions.js index 25d967e7f..8bfb5ce97 100644 --- a/src/serializer/functions.js +++ b/src/serializer/functions.js @@ -370,7 +370,7 @@ export class Functions { }; let oldReportPropertyAccess = this.realm.reportPropertyAccess; this.realm.reportPropertyAccess = (pb: PropertyBinding) => { - if (pb.object.refuseSerialization) return; + if (ObjectValue.refuseSerializationOnPropertyBinding(pb)) return; let location = this.realm.currentLocation; if (!location) return; // happens only when accessing an additional function property if (pbs.has(pb) && !conflicts.has(location)) reportConflict(location); diff --git a/src/serializer/utils.js b/src/serializer/utils.js index d58e1df77..9aca6a173 100644 --- a/src/serializer/utils.js +++ b/src/serializer/utils.js @@ -217,12 +217,14 @@ export function handleReportedSideEffect( exceptionHandler(`side-effects from mutating the binding ${name}${location}`); } else if (sideEffectType === "MODIFIED_PROPERTY" || sideEffectType === "MODIFIED_GLOBAL") { let name = ""; - let key = ((binding: any): PropertyBinding).key; + let pb = ((binding: any): PropertyBinding); + let key = pb.key; if (typeof key === "string") { name = `"${key}"`; } if (sideEffectType === "MODIFIED_PROPERTY") { - exceptionHandler(`side-effects from mutating a property ${name}${location}`); + if (!ObjectValue.refuseSerializationOnPropertyBinding(pb)) + exceptionHandler(`side-effects from mutating a property ${name}${location}`); } else { exceptionHandler(`side-effects from mutating the global object property ${name}${location}`); } diff --git a/src/utils/generator.js b/src/utils/generator.js index 22267c5ab..7ef59b182 100644 --- a/src/utils/generator.js +++ b/src/utils/generator.js @@ -559,7 +559,7 @@ export class Generator { for (let propertyBinding of modifiedProperties.keys()) { let object = propertyBinding.object; if (createdObjects.has(object)) continue; // Created Object's binding - if (object.refuseSerialization) continue; // modification to internal state + if (ObjectValue.refuseSerializationOnPropertyBinding(propertyBinding)) continue; // modification to internal state // modifications to intrinsic objects are tracked in the generator if (object.isIntrinsic()) continue; output.emitPropertyModification(propertyBinding); diff --git a/src/values/ObjectValue.js b/src/values/ObjectValue.js index 91b04de5c..6ac567983 100644 --- a/src/values/ObjectValue.js +++ b/src/values/ObjectValue.js @@ -1074,4 +1074,10 @@ export default class ObjectValue extends ConcreteValue { $OwnPropertyKeys(): Array { return OrdinaryOwnPropertyKeys(this.$Realm, this); } + + static refuseSerializationOnPropertyBinding(pb: PropertyBinding): boolean { + if (pb.object.refuseSerialization) return true; + if (pb.internalSlot && typeof pb.key === "string" && pb.key[0] === "_") return true; + return false; + } } diff --git a/test/serializer/optimized-functions/Issue2262Regression.js b/test/serializer/optimized-functions/Issue2262Regression.js new file mode 100644 index 000000000..c3c98a967 --- /dev/null +++ b/test/serializer/optimized-functions/Issue2262Regression.js @@ -0,0 +1,19 @@ +(function() { + let p = {}; + function f(c) { + let o = {}; + if (c) { + if (global.__makePartial) __makePartial(o); + throw o; + } + } + if (global.__optimize) __optimize(f); + inspect = function() { + try { + f(true); + return false; + } catch (e) { + return true; + } + }; +})(); diff --git a/test/serializer/optimized-functions/Issue2266Regression.js b/test/serializer/optimized-functions/Issue2266Regression.js new file mode 100644 index 000000000..2b6666767 --- /dev/null +++ b/test/serializer/optimized-functions/Issue2266Regression.js @@ -0,0 +1,12 @@ +// expected Warning: +function outer() { + function inner() { + return 42; + } + if (global.__optimize) __optimize(inner); + return inner; +} +if (global.__optimize) __optimize(outer); +global.inspect = function() { + return outer()(); +};