public void GenerateDelete(ILGenerator generator, OptimizationInfo optimizationInfo)
{
// Deleting a variable is not allowed in strict mode.
if (optimizationInfo.StrictMode == true)
throw new JavaScriptException(optimizationInfo.Engine, ErrorType.SyntaxError, string.Format("Cannot delete {0} because deleting a variable or argument is not allowed in strict mode", this.Name), optimizationInfo.SourceSpan.StartLine, optimizationInfo.Source.Path, optimizationInfo.FunctionName);
var endOfDelete = generator.CreateLabel();
var scope = this.Scope;
ILLocalVariable scopeVariable = generator.CreateTemporaryVariable(typeof(Scope));
EmitHelpers.LoadScope(generator);
generator.StoreVariable(scopeVariable);
do
{
if (scope is DeclarativeScope)
{
var variable = scope.GetDeclaredVariable(this.Name);
if (variable != null)
{
// The variable is known at compile-time.
if (variable.Deletable == false)
{
// The variable cannot be deleted - return false.
generator.LoadBoolean(false);
}
else
{
// The variable can be deleted (it was declared inside an eval()).
// Delete the variable.
generator.LoadVariable(scopeVariable);
generator.CastClass(typeof(DeclarativeScope));
generator.LoadString(this.Name);
generator.Call(ReflectionHelpers.Scope_Delete);
}
break;
}
else
{
// The variable was not defined at compile time, but may have been
// introduced by an eval() statement.
if (optimizationInfo.MethodOptimizationHints.HasEval == true)
{
// Check the variable exists: if (scope.HasValue(variableName) == true) {
generator.LoadVariable(scopeVariable);
generator.CastClass(typeof(DeclarativeScope));
generator.LoadString(this.Name);
generator.Call(ReflectionHelpers.Scope_HasValue);
var hasValueClause = generator.CreateLabel();
generator.BranchIfFalse(hasValueClause);
// If the variable does exist, return true.
generator.LoadVariable(scopeVariable);
generator.CastClass(typeof(DeclarativeScope));
generator.LoadString(this.Name);
generator.Call(ReflectionHelpers.Scope_Delete);
generator.Branch(endOfDelete);
// }
generator.DefineLabelPosition(hasValueClause);
}
}
}
else
{
// Check if the property exists by calling scope.ScopeObject.HasProperty(propertyName)
generator.LoadVariable(scopeVariable);
generator.CastClass(typeof(ObjectScope));
generator.Call(ReflectionHelpers.ObjectScope_ScopeObject);
generator.Duplicate();
generator.LoadString(this.Name);
generator.Call(ReflectionHelpers.ObjectInstance_HasProperty);
// Jump past the delete if the property doesn't exist.
var endOfExistsCheck = generator.CreateLabel();
generator.BranchIfFalse(endOfExistsCheck);
// Call scope.ScopeObject.Delete(key, false)
generator.LoadString(this.Name);
generator.LoadBoolean(false);
generator.Call(ReflectionHelpers.ObjectInstance_Delete);
generator.Branch(endOfDelete);
generator.DefineLabelPosition(endOfExistsCheck);
generator.Pop();
// If the name is not defined, return true.
if (scope.ParentScope == null)
{
generator.LoadBoolean(true);
}
}
// Try the parent scope.
if (scope.ParentScope != null && scope.ExistsAtRuntime == true)
{
generator.LoadVariable(scopeVariable);
generator.Call(ReflectionHelpers.Scope_ParentScope);
generator.StoreVariable(scopeVariable);
}
scope = scope.ParentScope;
} while (scope != null);
// Release the temporary variable.
generator.ReleaseTemporaryVariable(scopeVariable);
// Define a label at the end.
generator.DefineLabelPosition(endOfDelete);
// Delete obviously has side-effects so we evaluate the return value then pop it from
// the stack.
//if (optimizationInfo.SuppressReturnValue == true)
// generator.Pop();
}