Преглед на файлове

Use lazy evaluation for events from attributes. Is more consistent with existing events.

Martijn Laan преди 6 години
родител
ревизия
09fc3e6912
променени са 6 файла, в които са добавени 28 реда и са изтрити 29 реда
  1. 3 3
      ISHelp/isx.xml
  2. 1 1
      Projects/Install.pas
  3. 2 2
      Projects/Main.pas
  4. 14 15
      Projects/ScriptRunner.pas
  5. 2 2
      Projects/Uninstall.pas
  6. 6 6
      Projects/Wizard.pas

+ 3 - 3
ISHelp/isx.xml

@@ -314,10 +314,10 @@ end;
 
 
 <ul>
 <ul>
 <li>The implementations will be called in order of their definition except that any main implementation (=the implementation without an event attribute) will be called last.</li>
 <li>The implementations will be called in order of their definition except that any main implementation (=the implementation without an event attribute) will be called last.</li>
-<li>Event attributes may only be used for event functions which are a procedure or are a function which return a Boolean. In the latter case:</li>
+<li>Event attributes may only be used for event functions which are a procedure or are a function which return a Boolean. In the latter case lazy evaluation is performed:</li>
 <ul>
 <ul>
-<li><tt>InitializeSetup</tt>, <tt>BackButtonClick</tt>, <tt>NextButtonClick</tt>, <tt>InitializeUninstall</tt>: All implementations must return True for the event function to be treated as returning True and an implementation returning False does not stop the calls to the other implementations. In other words: the results are 'and'-ed without lazy evaluation.</li>
-<li><tt>CheckPassword</tt>, <tt>CheckSerial</tt>, <tt>ShouldSkipPage</tt>, <tt>NeedRestart</tt>: One implementation must return True for the event function to be treated as returning True and an implementation returning True does not stop the calls to the other implementations. In other words: the results are 'or'-ed without lazy evaluation.</li>
+<li><tt>InitializeSetup</tt>, <tt>BackButtonClick</tt>, <tt>NextButtonClick</tt>, <tt>InitializeUninstall</tt>: All implementations must return True for the event function to be treated as returning True and an implementation returning False stops the calls to the other implementations.</li>
+<li><tt>CheckPassword</tt>, <tt>CheckSerial</tt>, <tt>ShouldSkipPage</tt>, <tt>NeedRestart</tt>: All implementation must return False for the event function to be treated as returning False and an implementation returning True stop the calls to the other implementations.</li>
 </ul>
 </ul>
 <li>Event attributes may only be used on procedures or functions which do not already have the name of an event function.</li>
 <li>Event attributes may only be used on procedures or functions which do not already have the name of an event function.</li>
 <li>If the event function uses <tt>var</tt> parameters then the value will be passed on from implementation to implementation.</li>
 <li>If the event function uses <tt>var</tt> parameters then the value will be passed on from implementation to implementation.</li>

+ 1 - 1
Projects/Install.pas

@@ -2920,7 +2920,7 @@ var
     if (CodeRunner <> nil) and CodeRunner.FunctionExists('NeedRestart', True) then begin
     if (CodeRunner <> nil) and CodeRunner.FunctionExists('NeedRestart', True) then begin
       if not NeedsRestart then begin
       if not NeedsRestart then begin
         try
         try
-          if CodeRunner.RunBooleanFunctions('NeedRestart', [''], False, False, False) then begin
+          if CodeRunner.RunBooleanFunctions('NeedRestart', [''], bcTrue, False, False) then begin
             NeedsRestart := True;
             NeedsRestart := True;
             Log('Will restart because NeedRestart returned True.');
             Log('Will restart because NeedRestart returned True.');
           end;
           end;

+ 2 - 2
Projects/Main.pas

@@ -2706,7 +2706,7 @@ var
       if shPassword in SetupHeader.Options then
       if shPassword in SetupHeader.Options then
         PasswordOk := TestPassword(S);
         PasswordOk := TestPassword(S);
       if not PasswordOk and (CodeRunner <> nil) then
       if not PasswordOk and (CodeRunner <> nil) then
-        PasswordOk := CodeRunner.RunBooleanFunctions('CheckPassword', [S], False, False, PasswordOk);
+        PasswordOk := CodeRunner.RunBooleanFunctions('CheckPassword', [S], bcTrue, False, PasswordOk);
 
 
       if PasswordOk then begin
       if PasswordOk then begin
         Result := False;
         Result := False;
@@ -3313,7 +3313,7 @@ begin
       raise;
       raise;
     end;
     end;
     try
     try
-      Res := CodeRunner.RunBooleanFunctions('InitializeSetup', [''], True, False, True);
+      Res := CodeRunner.RunBooleanFunctions('InitializeSetup', [''], bcFalse, False, True);
     except
     except
       Log('InitializeSetup raised an exception (fatal).');
       Log('InitializeSetup raised an exception (fatal).');
       raise;
       raise;

+ 14 - 15
Projects/ScriptRunner.pas

@@ -24,6 +24,8 @@ type
   TScriptRunnerOnDebugIntermediate = function(const Position: LongInt; var ContinueStepOver: Boolean): Boolean;
   TScriptRunnerOnDebugIntermediate = function(const Position: LongInt; var ContinueStepOver: Boolean): Boolean;
   TScriptRunnerOnException = procedure(const Exception: AnsiString; const Position: LongInt);
   TScriptRunnerOnException = procedure(const Exception: AnsiString; const Position: LongInt);
 
 
+  TBreakCondition = (bcNone, bcTrue, bcFalse);
+
   TScriptRunner = class
   TScriptRunner = class
     private
     private
       FNamingAttribute: String;
       FNamingAttribute: String;
@@ -37,7 +39,7 @@ type
       FOnException: TScriptRunnerOnException;
       FOnException: TScriptRunnerOnException;
       function GetProcNos(const Name: AnsiString; const CheckNamingAttribute: Boolean; const ProcNos: TPSList): Integer;
       function GetProcNos(const Name: AnsiString; const CheckNamingAttribute: Boolean; const ProcNos: TPSList): Integer;
       procedure InternalRunProcedure(const Name: AnsiString; const Parameters: array of Const; const CheckNamingAttribute, MustExist: Boolean);
       procedure InternalRunProcedure(const Name: AnsiString; const Parameters: array of Const; const CheckNamingAttribute, MustExist: Boolean);
-      function InternalRunBooleanFunction(const Name: AnsiString; const Parameters: array of Const; const CheckNamingAttribute, CheckNamingAttributeAndResults, MustExist, Default: Boolean): Boolean;
+      function InternalRunBooleanFunction(const Name: AnsiString; const Parameters: array of Const; const CheckNamingAttribute: Boolean; const BreakCondition: TBreakCondition; const MustExist, Default: Boolean): Boolean;
       procedure Log(const S: String);
       procedure Log(const S: String);
       procedure LogFmt(const S: String; const Args: array of const);
       procedure LogFmt(const S: String; const Args: array of const);
       procedure RaisePSExecException;
       procedure RaisePSExecException;
@@ -52,7 +54,7 @@ type
       procedure RunProcedure(const Name: AnsiString; const Parameters: array of Const; const MustExist: Boolean);
       procedure RunProcedure(const Name: AnsiString; const Parameters: array of Const; const MustExist: Boolean);
       procedure RunProcedures(const Name: AnsiString; const Parameters: array of Const; const MustExist: Boolean);
       procedure RunProcedures(const Name: AnsiString; const Parameters: array of Const; const MustExist: Boolean);
       function RunBooleanFunction(const Name: AnsiString; const Parameters: array of Const; const MustExist, Default: Boolean): Boolean;
       function RunBooleanFunction(const Name: AnsiString; const Parameters: array of Const; const MustExist, Default: Boolean): Boolean;
-      function RunBooleanFunctions(const Name: AnsiString; const Parameters: array of Const; const AndResults, MustExist, Default: Boolean): Boolean;
+      function RunBooleanFunctions(const Name: AnsiString; const Parameters: array of Const; const BreakCondition: TBreakCondition; const MustExist, Default: Boolean): Boolean;
       function RunIntegerFunction(const Name: AnsiString; const Parameters: array of Const; const MustExist: Boolean; const Default: Integer): Integer;
       function RunIntegerFunction(const Name: AnsiString; const Parameters: array of Const; const MustExist: Boolean; const Default: Integer): Integer;
       function RunStringFunction(const Name: AnsiString; const Parameters: array of Const; const MustExist: Boolean; const Default: String): String;
       function RunStringFunction(const Name: AnsiString; const Parameters: array of Const; const MustExist: Boolean; const Default: String): String;
       function EvaluateUsedVariable(const Param1, Param2, Param3: LongInt; const Param4: AnsiString): String;
       function EvaluateUsedVariable(const Param1, Param2, Param3: LongInt; const Param4: AnsiString): String;
@@ -455,17 +457,17 @@ begin
   InternalRunProcedure(Name, Parameters, True, MustExist);
   InternalRunProcedure(Name, Parameters, True, MustExist);
 end;
 end;
 
 
-function TScriptRunner.InternalRunBooleanFunction(const Name: AnsiString; const Parameters: array of Const; const CheckNamingAttribute, CheckNamingAttributeAndResults, MustExist, Default: Boolean): Boolean;
+function TScriptRunner.InternalRunBooleanFunction(const Name: AnsiString; const Parameters: array of Const; const CheckNamingAttribute: Boolean; const BreakCondition: TBreakCondition; const MustExist, Default: Boolean): Boolean;
 var
 var
   ProcNos, Params: TPSList;
   ProcNos, Params: TPSList;
   Res: PPSVariant;
   Res: PPSVariant;
-  ProcResult: Boolean;
   I: Integer;
   I: Integer;
 begin
 begin
   ProcNos := TPSList.Create;
   ProcNos := TPSList.Create;
   try
   try
     if GetProcNos(Name, CheckNamingAttribute, ProcNos) <> 0 then begin
     if GetProcNos(Name, CheckNamingAttribute, ProcNos) <> 0 then begin
-      Result := True; { Silence compiler }
+      if (BreakCondition = bcNone) and (ProcNos.Count > 1) then
+        InternalError('InternalRunBooleanFunction: invalid BreakCondition');
       for I := 0 to ProcNos.Count-1 do begin
       for I := 0 to ProcNos.Count-1 do begin
         Params := TPSList.Create();
         Params := TPSList.Create();
         try
         try
@@ -475,13 +477,10 @@ begin
           WriteBackParameters(Parameters, Params);
           WriteBackParameters(Parameters, Params);
 
 
           RaisePSExecException;
           RaisePSExecException;
-          ProcResult := PPSVariantU8(Res).Data = 1;
-          if I = 0 then
-            Result := ProcResult
-          else if CheckNamingAttributeAndResults then
-            Result := Result and ProcResult { Don't break on Result = False: need to call all procs always. }
-          else
-            Result := Result or ProcResult { Don't break on Result = True: need to call all procs always. }
+          Result := PPSVariantU8(Res).Data = 1;
+          if (Result and (BreakCondition = bcTrue)) or
+             (not Result and (BreakCondition = bcFalse)) then
+            Exit;
         finally
         finally
           FreePSVariantList(Params);
           FreePSVariantList(Params);
         end;
         end;
@@ -498,12 +497,12 @@ end;
 
 
 function TScriptRunner.RunBooleanFunction(const Name: AnsiString; const Parameters: array of Const; const MustExist, Default: Boolean): Boolean;
 function TScriptRunner.RunBooleanFunction(const Name: AnsiString; const Parameters: array of Const; const MustExist, Default: Boolean): Boolean;
 begin
 begin
-  Result := InternalRunBooleanFunction(Name, Parameters, False, False, MustExist, Default);
+  Result := InternalRunBooleanFunction(Name, Parameters, False, bcNone, MustExist, Default);
 end;
 end;
 
 
-function TScriptRunner.RunBooleanFunctions(const Name: AnsiString; const Parameters: array of Const; const AndResults, MustExist, Default: Boolean): Boolean;
+function TScriptRunner.RunBooleanFunctions(const Name: AnsiString; const Parameters: array of Const; const BreakCondition: TBreakCondition; const MustExist, Default: Boolean): Boolean;
 begin
 begin
-  Result := InternalRunBooleanFunction(Name, Parameters, True, AndResults, MustExist, Default);
+  Result := InternalRunBooleanFunction(Name, Parameters, True, BreakCondition, MustExist, Default);
 end;
 end;
 
 
 function TScriptRunner.RunIntegerFunction(const Name: AnsiString; const Parameters: array of Const; const MustExist: Boolean; const Default: Integer): Integer;
 function TScriptRunner.RunIntegerFunction(const Name: AnsiString; const Parameters: array of Const; const MustExist: Boolean; const Default: Integer): Integer;

+ 2 - 2
Projects/Uninstall.pas

@@ -603,7 +603,7 @@ begin
       try
       try
         if CodeRunner <> nil then begin
         if CodeRunner <> nil then begin
           try
           try
-            Res := CodeRunner.RunBooleanFunctions('InitializeUninstall', [''], True, False, True);
+            Res := CodeRunner.RunBooleanFunctions('InitializeUninstall', [''], bcFalse, False, True);
           except
           except
             Log('InitializeUninstall raised an exception (fatal).');
             Log('InitializeUninstall raised an exception (fatal).');
             raise;
             raise;
@@ -657,7 +657,7 @@ begin
         if (CodeRunner <> nil) and CodeRunner.FunctionExists('UninstallNeedRestart', True) then begin
         if (CodeRunner <> nil) and CodeRunner.FunctionExists('UninstallNeedRestart', True) then begin
           if not UninstallNeedsRestart then begin
           if not UninstallNeedsRestart then begin
             try
             try
-              if CodeRunner.RunBooleanFunctions('UninstallNeedRestart', [''], False, False, False) then begin
+              if CodeRunner.RunBooleanFunctions('UninstallNeedRestart', [''], bcTrue, False, False) then begin
                 UninstallNeedsRestart := True;
                 UninstallNeedsRestart := True;
                 Log('Will restart because UninstallNeedRestart returned True.');
                 Log('Will restart because UninstallNeedRestart returned True.');
               end;
               end;

+ 6 - 6
Projects/Wizard.pas

@@ -250,7 +250,7 @@ implementation
 
 
 uses
 uses
   ShellApi, ShlObj, Types, Msgs, Main, PathFunc, CmnFunc, CmnFunc2,
   ShellApi, ShlObj, Types, Msgs, Main, PathFunc, CmnFunc, CmnFunc2,
-  MD5, InstFunc, SelFolderForm, Extract, Logging, RestartManager;
+  MD5, InstFunc, SelFolderForm, Extract, Logging, RestartManager, ScriptRunner;
 
 
 {$R *.DFM}
 {$R *.DFM}
 
 
@@ -431,7 +431,7 @@ begin
     WizardUserInfoName := UserInfoNameEdit.Text;
     WizardUserInfoName := UserInfoNameEdit.Text;
     WizardUserInfoOrg := UserInfoOrgEdit.Text;
     WizardUserInfoOrg := UserInfoOrgEdit.Text;
     WizardUserInfoSerial := UserInfoSerialEdit.Text;
     WizardUserInfoSerial := UserInfoSerialEdit.Text;
-    Result := CodeRunner.RunBooleanFunctions('CheckSerial', [UserInfoSerialEdit.Text], False, True, False)
+    Result := CodeRunner.RunBooleanFunctions('CheckSerial', [UserInfoSerialEdit.Text], bcTrue, True, False)
   end else
   end else
     Result := True;
     Result := True;
 end;
 end;
@@ -2042,7 +2042,7 @@ begin
     if not Result then begin
     if not Result then begin
       try
       try
         if CodeRunner <> nil then
         if CodeRunner <> nil then
-          Result := CodeRunner.RunBooleanFunctions('ShouldSkipPage', [PageID], False, False, Result);
+          Result := CodeRunner.RunBooleanFunctions('ShouldSkipPage', [PageID], bcTrue, False, Result);
       except
       except
         Application.HandleException(Self);
         Application.HandleException(Self);
       end;
       end;
@@ -2063,7 +2063,7 @@ procedure TWizardForm.NextButtonClick(Sender: TObject);
     if shPassword in SetupHeader.Options then
     if shPassword in SetupHeader.Options then
       Result := TestPassword(S);
       Result := TestPassword(S);
     if not Result and (CodeRunner <> nil) then
     if not Result and (CodeRunner <> nil) then
-      Result := CodeRunner.RunBooleanFunctions('CheckPassword', [S], False, False, Result);
+      Result := CodeRunner.RunBooleanFunctions('CheckPassword', [S], bcTrue, False, Result);
 
 
     if Result then begin
     if Result then begin
       NeedPassword := False;
       NeedPassword := False;
@@ -2228,7 +2228,7 @@ begin
     Exit;
     Exit;
 
 
   if CodeRunner <> nil then
   if CodeRunner <> nil then
-    if CodeRunner.RunBooleanFunctions('NextButtonClick', [CurPageID], True, False, True) = False then
+    if CodeRunner.RunBooleanFunctions( 'NextButtonClick', [CurPageID], bcFalse, False, True) = False then
       Exit;
       Exit;
 
 
   { Go to the next page, or close wizard if it was on the last page }
   { Go to the next page, or close wizard if it was on the last page }
@@ -2328,7 +2328,7 @@ begin
     Exit;
     Exit;
 
 
   if CodeRunner <> nil then
   if CodeRunner <> nil then
-    if CodeRunner.RunBooleanFunctions('BackButtonClick', [CurPageID], True, False, True) = False then
+    if CodeRunner.RunBooleanFunctions('BackButtonClick', [CurPageID], bcFalse, False, True) = False then
       Exit;
       Exit;
 
 
   PrevPageID := GetPreviousPageID;
   PrevPageID := GetPreviousPageID;