Hi all,
I'm trying to follow the Essential ActionScript 3.0 book and I've hit a snag in chapter 22 at the CustomMousePointerDemo class. I'm using CS4 to compile with a CustomMousePointerDemo as the document class. I get this:

TypeError: Error #1009: Cannot access a property or method of a null object reference.
at StageDetector/registerListeners()
at StageDetector/setWatchedRoot()
at StageDetector/setWatchedObject()
at StageDetector()
at CustomMousePointer()
at CustomMousePointerDemo()


when I try to test the movie.

here is the CustomMousePointerDemo
Code:
// File CustomMousePointerDemo.as

package {
	import flash.display.*;
	
	// Demonstrates the use of the CustomMousePointer class
	public class CustomMousePointerDemo extends Sprite{
		private var pointer:CustomMousePointer;
		
		// Constructor
		public function CustomMousePointerDemo(){
			// Create a new CustomMousePointer object and add it to the display list.  The act of
			// adding the customMousePointer to the display list automatically replaces the system mouse pointer
			// with the CustomMousePointer object
			pointer = new CustomMousePointer();
			addChild(pointer);
 		}
	}
}
The StageDetector class uses the stage instance variable to determine whether an object is on the display list or not. My guess is that this is where the problem is but I can't figure out why. Here is the StageDetector

Code:
// File StageDetector.as

package {
	import flash.display.*;
	import flash.events.*;
	
	// Monitors a specified display object to see when it is added to or removed from the stage, and broadcasts the corresponding custom events
	// StageDetector.ADDED_TO_STAGE and StageDetector.REMOVED_FROM_STAGE.
	
	// USAGE:
	// var stageDetector:StageDetector = new StageDetector(someDisplayObject);
	// stageDetector.addEventListener(StageDetector.ADDED_TO_STAGE, addedToStageListenerFunction);
	// stageDetector.addEventListener(StageDetector.REMOVED_FROM_STAGE, removedFromStageListenerFunction);
	
	public class StageDetector extends EventDispatcher {
		// Event Constants
		public static const ADDED_TO_STAGE:String = "ADDED_TO_STAGE";
		public static const REMOVED_FROM_STAGE:String = "REMOVED_FROM_STAGE";
		
		// The object for which ADDED_TO_STAGE and REMOVED_FROM_STAGE events will be generated
		private var watchedObject:DisplayObject = null;
		
		// The root of the display hierarchy that contains watchedObject
		private var watchedRoot:DisplayObject = null;
		
		// Flag indicating whether watchedObject is currently on the display list
		private var onStage:Boolean = false;
		
		// Constructor
		public function StageDetector(objectToWatch:DisplayObject) {
			// Begin monitoring the specified object
			setWatchedObject(objectToWatch);
		}
		
		// Begins monitoring the specified object to see when it is added to or removed from the display list
		public function setWatchedObject(objectToWatch:DisplayObject):void {
			// Track the object being monitored
			watchedObject = objectToWatch;
			
			// Note whether watchedObject is currently on the display list
			if (watchedObject.stage != null) {
				onStage = true;
			}
			
			// Find the root of the display hierarchy containing the watchedObject, and register with it for ADDED/REMOVED events.
			// By observering where watchedObject's root is added and removed we'll determin whether watchedObject is on or 
			// off the display list.
			setWatchedRoot(findWatchedObjectRoot());
		}
		
		// Returns a reference to the object being monitored
		public function getWatchedObject():DisplayObject {
			return watchedObject;
		}
		
		// Frees this StageDetector object's resources.  Call this before discarding a StageDetector object.
		public function dispose():void {
			clearWatchedRoot();
			watchedObject = null;
		}
		
		// Handles Event.ADDED events targeted at the root of watchedObject's display heirarchy
		private function addedListener(e:Event):void {
			// If the current watchedRoot was added...
			if(e.eventPhase == EventPhase.AT_TARGET) {
				// ...check if watchObject is now on the display list
				if(watchedObject.stage != null) {
					// Note that watchedObject is now on the display list
					onStage = true;
					// Notify listeners that watchedObject is now on the display list
					dispatchEvent(new Event(StageDetector.ADDED_TO_STAGE));
				}
				// watchedRoot was added to another container, so there's now a new root of the display hierarchy containing watchedObject
				// Find that new root, and register with it for ADDED and REMOVED events.
				setWatchedRoot(findWatchedObjectRoot());
			}
		}
		
		// Handles Event.REMOVED events for the root of watchedObject's display hierarchy
		private function removedListener(e:Event):void {
			// If watchedObject is on the display list...
			if(onStage) {
				//...check if watchedObject or one of it's ancestors was removed
				var wasRemoved:Boolean = false;
				var ancestor:DisplayObject = watchedObject;
				var target:DisplayObject = DisplayObject(e.target);
				while (ancestor != null) {
					if (target == ancestor) {
						wasRemoved = true;
						break;
					}
					ancestor = ancestor.parent;
				}
				
				// If watchedObject or one of it's ancestors was removed
				if(wasRemoved){
					//...register for ADDED and REMOVED events from the removed object
					// Which is the new root of watchedObject's display hierarchy
					setWatchedRoot(target);
					
					// Note that watchedObject is not on the display list anymore
					onStage = false;
					
					// Notifiy listeners that watchedObject was removed from the stage
					dispatchEvent(new Event(StageDetector.REMOVED_FROM_STAGE))
				}
			}
		}

		// returns the root of the display hierarchy that currently contains watchedObject
		private function findWatchedObjectRoot():DisplayObject {
			var watchedObjectRoot:DisplayObject = watchedObject;
			while(watchedObjectRoot != null){
				watchedObjectRoot = watchedObjectRoot.parent;
			}
			return watchedObjectRoot;
		}
		
		// Begins listening for ADDED and REMOVED events targeted at the root of watchedObject's display hierarchy
		private function setWatchedRoot (newWatchedRoot:DisplayObject):void {
			clearWatchedRoot();
			watchedRoot = newWatchedRoot;
			registerListeners(watchedRoot);
		}
		
		// Removes event listeners from watchedRoot, and removes this StageDetector's reference to watchedRoot
		private function clearWatchedRoot():void {
			if (watchedRoot != null) {
				unregisterListeners(watchedRoot);
				watchedRoot = null;
			}
		}
	
		// Registers ADDED and REMOVED event listeners with watchedRoot
		private function registerListeners(target:DisplayObject):void {
			target.addEventListener(Event.ADDED, addedListener);
			target.addEventListener(Event.REMOVED, removedListener);
		}
		
		// Unregisters ADDED and REMOVED event listeners from watchedRoot
		private function unregisterListeners(target:DisplayObject):void {
			target.removeEventListener(Event.ADDED, addedListener);
			target.removeEventListener(Event.REMOVED, removedListener);
		}
	}
}
I'm pretty sure that there are Event.addedToStage and Event.removedFromStage event types now but I wanted to keep with the book.

Thank you for your help.