Why is my `set` variable undefined?

tell application "Safari"
   open location theURL
   tell document 1 to repeat
      set result to ""
      set result to do JavaScript "document.readyState"
      if result = "complete" then exit repeat
      delay 0.5
      log "result: " & result
   end repeat
end tell

Frequently when I execute this code I get an error message saying that "result" is not defined on the log-statement. Why? Shouldn’t it at least be empty if the do JavaScript didn’t return something?

1 Like

do JavaScript “document.readyState” does not always work consistently. According to my observations, the following script gives a guaranteed result:

tell application "Safari"
	make new document with properties {URL:"https://www.macscripter.net/viewtopic.php?id=19262"}
	my waitSafariWebPageLoading()
	display dialog "The webpage is fully loaded now."
end tell

on waitSafariWebPageLoading()
	tell application "System Events" to tell application process "Safari"
		repeat until (UI element "Reload this page" of group 3 of toolbar 1 of window 1 exists) or (UI element "Reload this page" of group 2 of toolbar 1 of window 1 exists)
			delay 0.1
		end repeat
	end tell
end waitSafariWebPageLoading

Also, here is this, without GUI scripting, written by me in the past. It is guaranteed to work with all pages containing “html” tags.

-- script: Safari.app: Pause a Script until a Web Page has Loaded
-- written: by me, in the past

tell application "Safari"
	make new document with properties ¬
	my waitSafariWebPageLoading(10) -- maximum seconds to wait = 10 seconds
	if result is true then set theHTML to (source of document 1)
end tell

on waitSafariWebPageLoading(loadingWaitMaximumSeconds as integer)
	set lineChangingChars to {linefeed, return, character id 11, character id 12, character id 133, character id 8232, character id 8233}
	set {ATID, htmlEnding} to {AppleScript's text item delimiters, ""}
	tell application "Safari"
		repeat 100 * loadingWaitMaximumSeconds times -- wait maximum 5 seconds
			delay 0.1
			set AppleScript's text item delimiters to {"<", ">"}
				copy text item -2 of (get source of front document) to htmlEnding
			end try
			set AppleScript's text item delimiters to lineChangingChars
			set htmlEnding to text items of htmlEnding
			set AppleScript's text item delimiters to ""
			set htmlEnding to "<" & htmlEnding & ">"
			if htmlEnding is "</html>" then exit repeat
		end repeat
	end tell
	set AppleScript's text item delimiters to ATID
	if htmlEnding is "</html>" then return true
	display notification "The webpage loading failed"
	return false
end waitSafariWebPageLoading

I think @Fredrik71 answered the immediate question correctly. That is, you should not try to set the reserved variable result to “” or to the result of do JavaScript.

Also, the big problem is that sometimes readyState returns “complete”, but in fact, all the HTML content is not loaded, and trying to access some of its elements is impossible.

I found a solution/explanation here

Apparently, this is an “unexpected behaviour”, if not a blatant bug, in AS.

Is result a reserved word?

Technically, it is a property of the applescript constant.

Global Constants in AppleScript

1 Like

Thanks for the explanation.

Does that mean that assigning to properties of applescript is possible but may result in problematic behavior?

Are there situations where such an assignment makes sense?

Others would probably be able to answer that question better than I.

That said, text delimiters are included in that category and you can define them.

tab is one of the text constants and you can assign a value to it, e.g. set tab to 3 and then use set z to tab + 2 and it will return 5. You can do the same with linefeed. Within Script Editor, the term’s colour remains purple however (i.e. like a property) and not green (i.e. like a variable would be). And of course, if you then try `set x to “end” & linefeed & “beginning”, you won’t get two paragraphs… you’ll get the two words with a ‘3’ between them.

result is perhaps more complicated in that it is set again after every action. In lagr’s example, the do applescript would have automatically made it the result of the command and thus it was unnecessary to set it manually — although it would have changed again after another command.

version is also one of these constants and its value should change depending upon the context (i.e. getting the version for two different applications will produce two different numbers). You can set it to something different but it seems to get its value dynamically.

I don’t think there are any good situations but it’s conceivable that undefined or incorrect behaviour may let you accomplish something that you couldn’t otherwise.

If you really, really want to use a keyword (or otherwise predefined term) as a variable, you can enclose it in pipes, e.g. |result| or |linefeed|.

On that note, some of the ASObjC code that floats around here uses the term NSURL or variously, nsurl. My computer runs Sierra and this usage conflicts with something (Satimage, if I recall correctly) and I typically need to add pipes to get the code to compile, e.g. convert nsurl to |NSURL|. (I might be forgetting the specifics here.)

Mockman has answered chrillek’s question, and I’ve included below the results of my testing FWIW. The only instances I can envision setting a property of AppleScript is with text item delimiters and result, and the only instance I would set result is to missing value.

BTW, I agree with the other forum members that there does not seem to be any reason to use result in the OP’s script. The variable theResult (or any other valid variable name) would seem a better choice.

-- set theResult to result --> error "The variable result is not defined." number -2753 from result
set result to "OK" --> "OK"
display dialog result --> OK
set result to missing value --> missing value
display dialog result --> msng

set theVersion to version of AppleScript --> 2.8
set version of AppleScript to 3.0 --> 3.0
display dialog version of AppleScript --> 3

set piValue to pi --> 3.14159265359
set pi to 1 --> 1
display dialog pi --> 1

set theSpace to space --> " "
set space to "OK" --> "OK"
display dialog space --> OK

set theTID to text item delimiters --> {""}
set text item delimiters to "OK" --> "OK "
display dialog text item delimiters --> OK