protected function find_all($selector, $locator, $exception = false, $node = false, $timeout = false) {

        // Throw exception, so dev knows it is not supported.
        if ($selector === 'named') {
            $exception = 'Using the "named" selector is deprecated as of 3.1. '
                .' Use the "named_partial" or use the "named_exact" selector instead.';
            throw new ExpectationException($exception, $this->getSession());
        }

        // Generic info.
        if (!$exception) {

            // With named selectors we can be more specific.
            if (($selector == 'named_exact') || ($selector == 'named_partial')) {
                $exceptiontype = $locator[0];
                $exceptionlocator = $locator[1];

                // If we are in a @javascript session all contents would be displayed as HTML characters.
                if ($this->running_javascript()) {
                    $locator[1] = html_entity_decode($locator[1], ENT_NOQUOTES);
                }

            } else {
                $exceptiontype = $selector;
                $exceptionlocator = $locator;
            }

            $exception = new ElementNotFoundException($this->getSession(), $exceptiontype, null, $exceptionlocator);
        }

        $params = array('selector' => $selector, 'locator' => $locator);
        // Pushing $node if required.
        if ($node) {
            $params['node'] = $node;
        }

        // How much we will be waiting for the element to appear.
        if (!$timeout) {
            $timeout = self::get_timeout();
            $microsleep = false;
        } else {
            // Spinning each 0.1 seconds if the timeout was forced as we understand
            // that is a special case and is good to refine the performance as much
            // as possible.
            $microsleep = true;
        }

        // Waits for the node to appear if it exists, otherwise will timeout and throw the provided exception.
        return $this->spin(
            function($context, $args) {

                // If no DOM node provided look in all the page.
                if (empty($args['node'])) {
                    return $context->getSession()->getPage()->findAll($args['selector'], $args['locator']);
                }

                // For nodes contained in other nodes we can not use the basic named selectors
                // as they include unions and they would look for matches in the DOM root.
                $elementxpath = $context->getSession()->getSelectorsHandler()->selectorToXpath($args['selector'], $args['locator']);

                // Split the xpath in unions and prefix them with the container xpath.
                $unions = explode('|', $elementxpath);
                foreach ($unions as $key => $union) {
                    $union = trim($union);

                    // We are in the container node.
                    if (strpos($union, '.') === 0) {
                        $union = substr($union, 1);
                    } else if (strpos($union, '/') !== 0) {
                        // Adding the path separator in case it is not there.
                        $union = '/' . $union;
                    }
                    $unions[$key] = $args['node']->getXpath() . $union;
                }

                // We can not use usual Element::find() as it prefixes with DOM root.
                return $context->getSession()->getDriver()->find(implode('|', $unions));
            },
            $params,
            $timeout,
            $exception,
            $microsleep
        );
    }