/[suikacvs]/messaging/manakai/lib/Message/DOM/Document.pm
Suika

Contents of /messaging/manakai/lib/Message/DOM/Document.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.28 - (hide annotations) (download)
Sun Jan 13 06:37:46 2008 UTC (16 years, 10 months ago) by wakaba
Branch: MAIN
Changes since 1.27: +7 -2 lines
++ manakai/lib/Message/DOM/ChangeLog	13 Jan 2008 06:35:37 -0000
2008-01-13  Wakaba  <wakaba@suika.fam.cx>

	* Window.pm: New Perl module.

	* Document.pm (default_view): Implemented.

	* Element.pm (current_style): Implemented.

1 wakaba 1.21 ## NOTE: This module will be renamed as Document.pm.
2 wakaba 1.1
3 wakaba 1.21 package Message::DOM::Document;
4     use strict;
5 wakaba 1.28 our $VERSION=do{my @r=(q$Revision: 1.27 $=~/\d+/g);sprintf "%d."."%02d" x $#r,@r};
6 wakaba 1.21 push our @ISA, 'Message::DOM::Node', 'Message::IF::Document',
7     'Message::IF::DocumentTraversal', 'Message::IF::DocumentXDoctype',
8 wakaba 1.22 'Message::IF::DocumentSelector', # MUST in Selectors API spec
9 wakaba 1.21 'Message::IF::HTMLDocument';
10     require Message::DOM::Node;
11     use Char::Class::XML
12     qw/
13     InXML_NameStartChar10 InXMLNameStartChar11
14     InXMLNameChar10 InXMLNameChar11
15     InXML_NCNameStartChar10 InXMLNCNameStartChar11
16     InXMLNCNameChar10 InXMLNCNameChar11
17     /;
18    
19     sub ____new ($$) {
20     my $self = shift->SUPER::____new (undef);
21     $$self->{implementation} = $_[0];
22     $$self->{strict_error_checking} = 1;
23     $$self->{child_nodes} = [];
24     $$self->{'http://suika.fam.cx/www/2006/dom-config/strict-document-children'} = 1;
25     $$self->{'http://suika.fam.cx/www/2006/dom-config/dtd-default-attribute'} = 1;
26     $$self->{'http://suika.fam.cx/www/2006/dom-config/clone-entity-reference-subtree'} = 1;
27     $$self->{'error-handler'} = sub ($) {
28     ## NOTE: Same as one set by |setParameter| with |undef| value.
29     warn $_[0];
30     return $_[0]->severity != 3; # SEVERITY_FATAL_ERROR
31     };
32     return $self;
33     } # ____new
34    
35     sub AUTOLOAD {
36     my $method_name = our $AUTOLOAD;
37     $method_name =~ s/.*:://;
38     return if $method_name eq 'DESTROY';
39 wakaba 1.1
40     if ({
41 wakaba 1.21 ## Read-only attributes (trivial accessors)
42 wakaba 1.28 default_view => 1,
43 wakaba 1.21 implementation => 1,
44     }->{$method_name}) {
45     no strict 'refs';
46     eval qq{
47     sub $method_name (\$) {
48     return \${\$_[0]}->{$method_name};
49 wakaba 1.1 }
50 wakaba 1.21 };
51     goto &{ $AUTOLOAD };
52     } elsif ({
53     ## Read-write attributes (DOMString, trivial accessors)
54 wakaba 1.25 manakai_charset => 1,
55 wakaba 1.21 document_uri => 1,
56     input_encoding => 1,
57     }->{$method_name}) {
58     no strict 'refs';
59     eval qq{
60     sub $method_name (\$;\$) {
61     if (\@_ > 1) {
62     if (\${\$_[0]}->{strict_error_checking} and
63     \${\$_[0]}->{manakai_read_only}) {
64     report Message::DOM::DOMException
65     -object => \$_[0],
66     -type => 'NO_MODIFICATION_ALLOWED_ERR',
67     -subtype => 'READ_ONLY_NODE_ERR';
68     }
69     if (defined \$_[1]) {
70     \${\$_[0]}->{$method_name} = ''.\$_[1];
71     } else {
72     delete \${\$_[0]}->{$method_name};
73     }
74     }
75     return \${\$_[0]}->{$method_name};
76 wakaba 1.1 }
77 wakaba 1.21 };
78     goto &{ $AUTOLOAD };
79     } elsif ({
80     ## Read-write attributes (boolean, trivial accessors)
81     all_declarations_processed => 1,
82 wakaba 1.25 manakai_has_bom => 1,
83 wakaba 1.21 }->{$method_name}) {
84     no strict 'refs';
85     eval qq{
86     sub $method_name (\$;\$) {
87     if (\@_ > 1) {
88     if (\${\$_[0]}->{manakai_strict_error_checking} and
89     \${\$_[0]}->{manakai_read_only}) {
90     report Message::DOM::DOMException
91     -object => \$_[0],
92     -type => 'NO_MODIFICATION_ALLOWED_ERR',
93     -subtype => 'READ_ONLY_NODE_ERR';
94     }
95     if (\$_[1]) {
96     \${\$_[0]}->{$method_name} = 1;
97     } else {
98     delete \${\$_[0]}->{$method_name};
99 wakaba 1.1 }
100     }
101 wakaba 1.21 return \${\$_[0]}->{$method_name};
102     }
103     };
104     goto &{ $AUTOLOAD };
105     } elsif (my $module_name = {
106 wakaba 1.23 can_dispatch => 'Message::DOM::EventTargetNode',
107 wakaba 1.21 create_attribute => 'Message::DOM::Attr',
108     create_attribute_ns => 'Message::DOM::Attr',
109     create_attribute_definition => 'Message::DOM::AttributeDefinition',
110     create_cdata_section => 'Message::DOM::Text',
111     create_comment => 'Message::DOM::CharacterData',
112     create_document_fragment => 'Message::DOM::DocumentFragment',
113     create_document_type_definition => 'Message::DOM::DocumentType',
114     create_element => 'Message::DOM::Element',
115     create_element_ns => 'Message::DOM::Element',
116     create_element_type_definition => 'Message::DOM::ElementTypeDefinition',
117     create_entity_reference => 'Message::DOM::EntityReference',
118 wakaba 1.23 create_event => 'Message::DOM::EventTargetNode',
119 wakaba 1.21 create_general_entity => 'Message::DOM::Entity',
120     create_notation => 'Message::DOM::Notation',
121     create_processing_instruction => 'Message::DOM::ProcessingInstruction',
122     manakai_create_serial_walker => 'Message::DOM::SerialWalker',
123     create_text_node => 'Message::DOM::Text',
124     create_tree_walker => 'Message::DOM::TreeWalker',
125 wakaba 1.22 query_selector => 'Message::DOM::SelectorsAPI',
126     query_selector_all => 'Message::DOM::SelectorsAPI',
127 wakaba 1.27 ___query_selector_all => 'Message::DOM::SelectorsAPI',
128 wakaba 1.21 }->{$method_name}) {
129     eval qq{ require $module_name } or die $@;
130     goto &{ $AUTOLOAD };
131     } else {
132     require Carp;
133     Carp::croak (qq<Can't locate method "$AUTOLOAD">);
134 wakaba 1.1 }
135 wakaba 1.21 } # AUTOLOAD
136     sub implementation ($);
137     sub create_attribute ($$);
138     sub create_attribute_ns ($$$);
139     sub create_attribute_definition ($$);
140     sub create_cdata_section ($$);
141     sub create_comment ($$);
142     sub create_document_fragment ($);
143     sub create_document_type_definition ($$);
144     sub create_element ($$);
145     sub create_element_ns ($$$);
146     sub create_element_type_definition ($$);
147     sub create_entity_reference ($$);
148     sub create_general_entity ($$);
149     sub create_notation ($$);
150     sub create_processing_instruction ($$$);
151     sub create_text_node ($$);
152    
153     ## |Node| attributes
154    
155     sub base_uri ($) {
156     my $v = ${$_[0]}->{manakai_entity_base_uri};
157     if (defined $v) {
158     return $v;
159     } else {
160     return ${$_[0]}->{document_uri};
161 wakaba 1.13 }
162 wakaba 1.21 ## TODO: HTML5 <base>
163     } # base_uri
164 wakaba 1.1
165 wakaba 1.21 sub node_name () { '#document' }
166 wakaba 1.1
167 wakaba 1.21 sub node_type () { 9 } # DOCUMENT_NODE
168 wakaba 1.1
169 wakaba 1.21 sub text_content ($;$) {
170     my $self = shift;
171     if ($$self->{'http://suika.fam.cx/www/2006/dom-config/strict-document-children'}) {
172     return undef;
173 wakaba 1.1 } else {
174 wakaba 1.21 local $Error::Depth = $Error::Depth + 1;
175     return $self->SUPER::text_content (@_);
176 wakaba 1.1 }
177 wakaba 1.21 } # text_content
178 wakaba 1.1
179 wakaba 1.21 ## |Node| methods
180 wakaba 1.1
181 wakaba 1.21 sub adopt_node ($$) {
182     my ($self, $source) = @_;
183     ## TODO: Should we apply |copy-asis| configuration parameter to this method?
184 wakaba 1.1
185 wakaba 1.21 return undef unless UNIVERSAL::isa ($source, 'Message::DOM::Node');
186 wakaba 1.1
187 wakaba 1.21 my $strict = $self->strict_error_checking;
188     if ($strict and $$self->{manakai_read_only}) {
189     report Message::DOM::DOMException
190     -object => $self,
191     -type => 'NO_MODIFICATION_ALLOWED_ERR',
192     -subtype => 'READ_ONLY_NODE_ERR';
193     }
194 wakaba 1.1
195 wakaba 1.21 my $parent = $source->parent_node;
196     if ($strict and defined $parent and $$parent->{manakai_read_only}) {
197     report Message::DOM::DOMException
198     -object => $self,
199     -type => 'NO_MODIFICATION_ALLOWED_ERR',
200     -subtype => 'READ_ONLY_NODE_ERR';
201     }
202 wakaba 1.1
203 wakaba 1.21 my $nt = $source->node_type;
204     my $oe;
205     if ($nt == 2) { # ATTRIBUTE_NODE
206     $oe = $source->owner_element;
207     if ($strict and defined $oe and $$oe->{manakai_read_only}) {
208     report Message::DOM::DOMException
209     -object => $self,
210     -type => 'NO_MODIFICATION_ALLOWED_ERR',
211     -subtype => 'READ_ONLY_NODE_ERR';
212     }
213     } elsif ($nt == 9 or $nt == 10 or $nt == 6 or $nt == 12 or
214     $nt == 81001 or $nt == 81002) {
215     # DOCUMENT_NODE, DOCUMENT_TYPE_NODE, ENTITY_NODE, NOTATION_NODE,
216     # ELEMENT_TYPE_DEFINITION_NODE, ATTRIBUTE_DEFINITION_NODE
217     report Message::DOM::DOMException
218     -object => $self,
219     -type => 'NOT_SUPPORTED_ERR',
220     -subtype => 'ADOPT_NODE_TYPE_NOT_SUPPORTED_ERR';
221     }
222 wakaba 1.1
223 wakaba 1.21 my @change_od;
224     my @nodes = ($source);
225     while (@nodes) {
226     my $node = shift @nodes;
227     my $nt = $node->node_type;
228     if ($strict and $$node->{manakai_read_only}) {
229     report Message::DOM::DOMException
230     -object => $self,
231     -type => 'NO_MODIFICATION_ALLOWED_ERR',
232     -subtype => 'READ_ONLY_NODE_ERR';
233 wakaba 1.1 }
234    
235 wakaba 1.21 push @change_od, $node;
236     push @nodes, @{$node->child_nodes}, @{$node->attributes or []};
237     } # @nodes
238 wakaba 1.1
239 wakaba 1.21 local $Error::Depth = $Error::Depth + 1;
240 wakaba 1.1
241 wakaba 1.21 if (defined $parent) {
242     $parent->remove_child ($source);
243     } elsif (defined $oe) {
244     $oe->remove_attribute_node ($source);
245     }
246 wakaba 1.1
247 wakaba 1.21 return $source if $self eq $change_od[0]->owner_document;
248     ## NOTE: The array must have more than zero
249     ## nodes by definition. In addition,
250     ## it cannot contain document or document
251     ## type nodes in current implementation.
252 wakaba 1.1
253 wakaba 1.21 my @ud_node;
254     for my $n (@change_od) {
255     $$n->{owner_document} = $self;
256     Scalar::Util::weaken ($$n->{owner_document});
257     if ($$n->{user_data}) {
258     push @ud_node, $n;
259     }
260     }
261 wakaba 1.1
262 wakaba 1.21 for my $src (@ud_node) {
263     my $src_ud = $$src->{user_data};
264     for my $key (keys %{$src_ud}) {
265     my $dh = $src_ud->{$key}->[1];
266     if ($dh) {
267     $dh->(5, $key, $src_ud->{$key}->[0], $src, undef); # NODE_ADOPTED
268 wakaba 1.1 }
269     }
270     }
271    
272 wakaba 1.21 return $source;
273     } # adopt_node
274    
275     sub append_child ($$) {
276     ## NOTE: Overrides |Node|'s implementation.
277     my $self = $_[0];
278 wakaba 1.1
279 wakaba 1.21 ## NOTE: |$self_od| code here in some $self->node_type.
280 wakaba 1.1
281 wakaba 1.21 ## -- Node Type check
282     my @new_child;
283     my $new_child_parent;
284     if ($_[1]->node_type == 11) { # DOCUMENT_FRAGMENT_NODE
285     push @new_child, @{$_[1]->child_nodes};
286     $new_child_parent = $_[1];
287     } else {
288     @new_child = ($_[1]);
289     $new_child_parent = $_[1]->parent_node;
290     }
291 wakaba 1.1
292 wakaba 1.21 ## NOTE: Depends on $self->node_type:
293     if ($$self->{strict_error_checking}) {
294     my $child_od = $_[1]->owner_document || $_[1]; # might be DocumentType
295     if ($self ne $child_od and $child_od->node_type != 10) {
296     report Message::DOM::DOMException # DOCUMENT_TYPE_NODE
297     -object => $self,
298     -type => 'WRONG_DOCUMENT_ERR',
299     -subtype => 'EXTERNAL_OBJECT_ERR';
300     }
301    
302     if ($$self->{manakai_read_only} or
303     (@new_child and defined $new_child_parent and
304     $$new_child_parent->{manakai_read_only})) {
305     report Message::DOM::DOMException
306     -object => $self,
307     -type => 'NO_MODIFICATION_ALLOWED_ERR',
308     -subtype => 'READ_ONLY_NODE_ERR';
309     }
310    
311     ## NOTE: Only in |Document|:
312     my $strict_children = $self->dom_config->get_parameter
313     (q<http://suika.fam.cx/www/2006/dom-config/strict-document-children>);
314     if ($strict_children) {
315     my $has_el;
316     my $has_dt;
317     my $child_nt = $_[1]->node_type;
318     if ($child_nt == 1) { # ELEMENT_NODE
319     $has_el = 1;
320     } elsif ($child_nt == 10) { # DOCUMENT_TYPE_NODE
321     $has_dt = 1;
322     } elsif ($child_nt == 11) { # DOCUMENT_FRAGMENT_NODE
323     for my $cn (@{$_[1]->child_nodes}) {
324     my $cnt = $cn->node_type;
325     if ($cnt == 1) { # ELEMENT_NODE
326     if ($has_el) {
327     report Message::DOM::DOMException
328     -object => $self,
329     -type => 'HIERARCHY_REQUEST_ERR',
330     -subtype => 'CHILD_NODE_TYPE_ERR';
331     }
332     $has_el = 1;
333     } elsif ($cnt == 10) { # DOCUMENT_TYPE_NODE
334     ## NOTE: |DocumentType| node cannot be contained in
335     ## |DocumentFragment| in strict mode.
336     if ($has_dt) {
337     report Message::DOM::DOMException
338     -object => $self,
339     -type => 'HIERARCHY_REQUEST_ERR',
340     -subtype => 'CHILD_NODE_TYPE_ERR';
341     }
342     $has_dt = 1;
343     }
344     }
345     }
346    
347     if ($has_el) {
348     my $anode = $self->last_child;
349     while (defined $anode) {
350     if ($anode->node_type == 1) { # ELEMENT_NODE
351     report Message::DOM::DOMException
352     -object => $self,
353     -type => 'HIERARCHY_REQUEST_ERR',
354     -subtype => 'CHILD_NODE_TYPE_ERR';
355     }
356     $anode = $anode->previous_sibling;
357     }
358     } # has_el
359     if ($has_dt) {
360     my $anode = $self->last_child;
361     while (defined $anode) {
362     my $ant = $anode->node_type;
363     if ($ant == 1 or $ant == 10) { # ELEMENT_NODE or DOCUMENT_TYPE_NODE
364     report Message::DOM::DOMException
365     -object => $self,
366     -type => 'HIERARCHY_REQUEST_ERR',
367     -subtype => 'CHILD_NODE_TYPE_ERR';
368     }
369     $anode = $anode->previous_sibling;
370     }
371     } # has_dt
372     }
373 wakaba 1.1
374 wakaba 1.21 for my $cn (@new_child) {
375     unless ({
376     3, (not $strict_children), # TEXT_NODE
377     5, (not $strict_children), # ENTITY_REFERENCE_NODE
378     1, 1, # ELEMENT_NODE
379     4, (not $strict_children), # CDATA_SECTION_NODE
380     7, 1, # PROCESSING_INSTRUCTION_NODE
381     8, 1, # COMMENT_NODE
382     10, 1, # DOCUMENT_TYPE_NODE
383     }->{$cn->node_type}) {
384     report Message::DOM::DOMException
385     -object => $self,
386     -type => 'HIERARCHY_REQUEST_ERR',
387     -subtype => 'CHILD_NODE_TYPE_ERR';
388     }
389     }
390 wakaba 1.1
391 wakaba 1.21 ## NOTE: Ancestor check here in |Node|.
392     }
393 wakaba 1.1
394 wakaba 1.21 ## NOTE: "Insert at" code only in insert_before and replace_child
395 wakaba 1.1
396 wakaba 1.21 ## -- Removes from parent
397     if ($new_child_parent) {
398     if (@new_child == 1) {
399     my $v = $$new_child_parent->{child_nodes};
400     RP: for my $i (0..$#$v) {
401     if ($v->[$i] eq $new_child[0]) {
402     splice @$v, $i, 1, ();
403     last RP;
404     }
405     } # RP
406     } else {
407     @{$$new_child_parent->{child_nodes}} = ();
408     }
409     }
410 wakaba 1.1
411 wakaba 1.21 ## -- Rewrite the |parentNode| properties
412     for my $nc (@new_child) {
413     $$nc->{parent_node} = $self;
414     Scalar::Util::weaken ($$nc->{parent_node});
415     }
416 wakaba 1.1
417 wakaba 1.21 ## NOTE: Depends on method:
418     push @{$$self->{child_nodes}}, @new_child;
419 wakaba 1.1
420 wakaba 1.21 ## NOTE: Only in |Document|.
421     for (@new_child) {
422     delete $$_->{implementation};
423     $$_->{owner_document} = $self;
424     Scalar::Util::weaken ($$_->{owner_document});
425     }
426 wakaba 1.1
427 wakaba 1.21 return $_[1];
428     } # apepnd_child
429 wakaba 1.1
430 wakaba 1.21 sub manakai_append_text ($$) {
431     my $self = shift;
432     if ($$self->{'http://suika.fam.cx/www/2006/dom-config/strict-document-children'}) {
433     #
434     } else {
435     local $Error::Depth = $Error::Depth + 1;
436     return $self->SUPER::manakai_append_text (@_);
437     }
438     } # manakai_append_text
439 wakaba 1.1
440 wakaba 1.21 sub insert_before ($$) {
441     ## NOTE: Overrides |Node|'s implementation.
442     my $self = $_[0];
443 wakaba 1.1
444 wakaba 1.21 ## NOTE: |$self_od| code here depending on $self->node_type.
445 wakaba 1.1
446 wakaba 1.21 ## -- Node Type check
447     my @new_child;
448     my $new_child_parent;
449     if ($_[1]->node_type == 11) { # DOCUMENT_FRAGMENT_NODE
450     push @new_child, @{$_[1]->child_nodes};
451     $new_child_parent = $_[1];
452     } else {
453     @new_child = ($_[1]);
454     $new_child_parent = $_[1]->parent_node;
455     }
456 wakaba 1.1
457 wakaba 1.21 ## NOTE: Depends on $self->node_type:
458     if ($$self->{strict_error_checking}) {
459     my $child_od = $_[1]->owner_document || $_[1]; # might be DocumentType
460     if ($self ne $child_od and $child_od->node_type != 10) {
461     report Message::DOM::DOMException # DOCUMENT_TYPE_NODE
462     -object => $self,
463     -type => 'WRONG_DOCUMENT_ERR',
464     -subtype => 'EXTERNAL_OBJECT_ERR';
465     }
466    
467     if ($$self->{manakai_read_only} or
468     (@new_child and defined $new_child_parent and
469     $$new_child_parent->{manakai_read_only})) {
470     report Message::DOM::DOMException
471     -object => $self,
472     -type => 'NO_MODIFICATION_ALLOWED_ERR',
473     -subtype => 'READ_ONLY_NODE_ERR';
474     }
475    
476     ## NOTE: Only in |Document|:
477     my $strict_children = $self->dom_config->get_parameter
478     (q<http://suika.fam.cx/www/2006/dom-config/strict-document-children>);
479     if ($strict_children) {
480     my $has_el;
481     my $has_dt;
482     my $child_nt = $_[1]->node_type;
483     if ($child_nt == 1) { # ELEMENT_NODE
484     $has_el = 1;
485     } elsif ($child_nt == 10) { # DOCUMENT_TYPE_NODE
486     $has_dt = 1;
487     } elsif ($child_nt == 11) { # DOCUMENT_FRAGMENT_NODE
488     for my $cn (@{$_[1]->child_nodes}) {
489     my $cnt = $cn->node_type;
490     if ($cnt == 1) { # ELEMENT_NODE
491     if ($has_el) {
492     report Message::DOM::DOMException
493     -object => $self,
494     -type => 'HIERARCHY_REQUEST_ERR',
495     -subtype => 'CHILD_NODE_TYPE_ERR';
496     }
497     $has_el = 1;
498     } elsif ($cnt == 10) { # DOCUMENT_TYPE_NODE
499     ## NOTE: |DocumentType| node cannot be contained in
500     ## |DocumentFragment| in strict mode.
501     if ($has_dt) {
502     report Message::DOM::DOMException
503     -object => $self,
504     -type => 'HIERARCHY_REQUEST_ERR',
505     -subtype => 'CHILD_NODE_TYPE_ERR';
506     }
507     $has_dt = 1;
508     }
509     }
510 wakaba 1.1 }
511    
512 wakaba 1.21 ## ISSUE: This code is wrong. Old manakai's implementation
513     ## is better, but it is also wrong in some edge cases.
514     ## Maybe we should remove these code entirely. DOM3Core
515     ## conformance is not important for this bit. It only makes
516     ## things too complex. Same for replace_child's code.
517     if ($has_el) {
518     my $anode = $self->last_child;
519     while (defined $anode) {
520     if ($anode->node_type == 1) { # ELEMENT_NODE
521     report Message::DOM::DOMException
522     -object => $self,
523     -type => 'HIERARCHY_REQUEST_ERR',
524     -subtype => 'CHILD_NODE_TYPE_ERR';
525 wakaba 1.1 }
526 wakaba 1.21 $anode = $anode->previous_sibling;
527 wakaba 1.1 }
528 wakaba 1.21 } # has_el
529     if ($has_dt) {
530     my $anode = $self->last_child;
531     while (defined $anode) {
532     my $ant = $anode->node_type;
533     if ($ant == 1 or $ant == 10) { # ELEMENT_NODE or DOCUMENT_TYPE_NODE
534     report Message::DOM::DOMException
535     -object => $self,
536     -type => 'HIERARCHY_REQUEST_ERR',
537     -subtype => 'CHILD_NODE_TYPE_ERR';
538     }
539     $anode = $anode->previous_sibling;
540     }
541     } # has_dt
542     }
543 wakaba 1.1
544 wakaba 1.21 for my $cn (@new_child) {
545     unless ({
546     3, (not $strict_children), # TEXT_NODE
547     5, (not $strict_children), # ENTITY_REFERENCE_NODE
548     1, 1, # ELEMENT_NODE
549     4, (not $strict_children), # CDATA_SECTION_NODE
550     7, 1, # PROCESSING_INSTRUCTION_NODE
551     8, 1, # COMMENT_NODE
552     10, 1, # DOCUMENT_TYPE_NODE
553     }->{$cn->node_type}) {
554     report Message::DOM::DOMException
555     -object => $self,
556     -type => 'HIERARCHY_REQUEST_ERR',
557     -subtype => 'CHILD_NODE_TYPE_ERR';
558     }
559     }
560 wakaba 1.1
561 wakaba 1.21 ## NOTE: Ancestor check here in |Node|.
562     }
563    
564     ## -- Insert at... ## NOTE: Only in insert_before and replace_child
565     my $index = -1; # last
566     if (defined $_[2]) {
567     ## error if $_[1] eq $_[2];
568    
569     my $cns = $self->child_nodes;
570     my $cnsl = @$cns;
571     C: {
572     $index = 0;
573     for my $i (0..($cnsl-1)) {
574     my $cn = $cns->[$i];
575     if ($cn eq $_[2]) {
576     $index += $i;
577     last C;
578     } elsif ($cn eq $_[1]) {
579     $index = -1; # offset
580     }
581     }
582 wakaba 1.1
583 wakaba 1.21 report Message::DOM::DOMException
584     -object => $self,
585     -type => 'NOT_FOUND_ERR',
586     -subtype => 'NOT_CHILD_ERR';
587     } # C
588     }
589     ## NOTE: "else" only in replace_child
590 wakaba 1.1
591 wakaba 1.21 ## -- Removes from parent
592     if ($new_child_parent) {
593     if (@new_child == 1) {
594     my $v = $$new_child_parent->{child_nodes};
595     RP: for my $i (0..$#$v) {
596     if ($v->[$i] eq $new_child[0]) {
597     splice @$v, $i, 1, ();
598     last RP;
599     }
600     } # RP
601     } else {
602     @{$$new_child_parent->{child_nodes}} = ();
603     }
604     }
605 wakaba 1.1
606 wakaba 1.21 ## -- Rewrite the |parentNode| properties
607     for my $nc (@new_child) {
608     $$nc->{parent_node} = $self;
609     Scalar::Util::weaken ($$nc->{parent_node});
610     }
611 wakaba 1.1
612 wakaba 1.21 ## NOTE: Depends on method:
613     if ($index == -1) {
614     push @{$$self->{child_nodes}}, @new_child;
615     } else {
616     splice @{$$self->{child_nodes}}, $index, 0, @new_child;
617     }
618 wakaba 1.1
619 wakaba 1.21 ## NOTE: Only in |Document|.
620     for (@new_child) {
621     delete $$_->{implementation};
622     $$_->{owner_document} = $self;
623     Scalar::Util::weaken ($$_->{owner_document});
624     }
625 wakaba 1.1
626 wakaba 1.21 return $_[1];
627     } # insert_before
628 wakaba 1.1
629 wakaba 1.21 sub replace_child ($$) {
630     ## NOTE: Overrides |Node|'s implementation.
631     my $self = $_[0];
632 wakaba 1.1
633 wakaba 1.21 ## NOTE: |$self_od| code here depending on $self->node_type.
634 wakaba 1.1
635 wakaba 1.21 ## -- Node Type check
636     my @new_child;
637     my $new_child_parent;
638     if ($_[1]->node_type == 11) { # DOCUMENT_FRAGMENT_NODE
639     push @new_child, @{$_[1]->child_nodes};
640     $new_child_parent = $_[1];
641     } else {
642     @new_child = ($_[1]);
643     $new_child_parent = $_[1]->parent_node;
644     }
645 wakaba 1.1
646 wakaba 1.21 ## NOTE: Depends on $self->node_type:
647     if ($$self->{strict_error_checking}) {
648     my $child_od = $_[1]->owner_document || $_[1]; # might be DocumentType
649     if ($self ne $child_od and $child_od->node_type != 10) {
650     report Message::DOM::DOMException # DOCUMENT_TYPE_NODE
651     -object => $self,
652     -type => 'WRONG_DOCUMENT_ERR',
653     -subtype => 'EXTERNAL_OBJECT_ERR';
654     }
655    
656     if ($$self->{manakai_read_only} or
657     (@new_child and defined $new_child_parent and
658     $$new_child_parent->{manakai_read_only})) {
659     report Message::DOM::DOMException
660     -object => $self,
661     -type => 'NO_MODIFICATION_ALLOWED_ERR',
662     -subtype => 'READ_ONLY_NODE_ERR';
663     }
664    
665     ## NOTE: Only in |Document|:
666     my $strict_children = $self->dom_config->get_parameter
667     (q<http://suika.fam.cx/www/2006/dom-config/strict-document-children>);
668     if ($strict_children) {
669     my $has_el;
670     my $has_dt;
671     my $child_nt = $_[1]->node_type;
672     if ($child_nt == 1) { # ELEMENT_NODE
673     $has_el = 1;
674     } elsif ($child_nt == 10) { # DOCUMENT_TYPE_NODE
675     $has_dt = 1;
676     } elsif ($child_nt == 11) { # DOCUMENT_FRAGMENT_NODE
677     for my $cn (@{$_[1]->child_nodes}) {
678     my $cnt = $cn->node_type;
679     if ($cnt == 1) { # ELEMENT_NODE
680     if ($has_el) {
681     report Message::DOM::DOMException
682     -object => $self,
683     -type => 'HIERARCHY_REQUEST_ERR',
684     -subtype => 'CHILD_NODE_TYPE_ERR';
685     }
686     $has_el = 1;
687     } elsif ($cnt == 10) { # DOCUMENT_TYPE_NODE
688     ## NOTE: |DocumentType| node cannot be contained in
689     ## |DocumentFragment| in strict mode.
690     if ($has_dt) {
691     report Message::DOM::DOMException
692     -object => $self,
693     -type => 'HIERARCHY_REQUEST_ERR',
694     -subtype => 'CHILD_NODE_TYPE_ERR';
695     }
696     $has_dt = 1;
697     }
698     }
699     }
700    
701     if ($has_el) {
702     my $anode = $self->last_child;
703     while (defined $anode) {
704     if ($anode->node_type == 1) { # ELEMENT_NODE
705     report Message::DOM::DOMException
706     -object => $self,
707     -type => 'HIERARCHY_REQUEST_ERR',
708     -subtype => 'CHILD_NODE_TYPE_ERR';
709     }
710     $anode = $anode->previous_sibling;
711     }
712     } # has_el
713     if ($has_dt) {
714     my $anode = $self->last_child;
715     while (defined $anode) {
716     my $ant = $anode->node_type;
717     if ($ant == 1 or $ant == 10) { # ELEMENT_NODE or DOCUMENT_TYPE_NODE
718     report Message::DOM::DOMException
719     -object => $self,
720     -type => 'HIERARCHY_REQUEST_ERR',
721     -subtype => 'CHILD_NODE_TYPE_ERR';
722     }
723     $anode = $anode->previous_sibling;
724     }
725     } # has_dt
726     }
727 wakaba 1.1
728 wakaba 1.21 for my $cn (@new_child) {
729     unless ({
730     3, (not $strict_children), # TEXT_NODE
731     5, (not $strict_children), # ENTITY_REFERENCE_NODE
732     1, 1, # ELEMENT_NODE
733     4, (not $strict_children), # CDATA_SECTION_NODE
734     7, 1, # PROCESSING_INSTRUCTION_NODE
735     8, 1, # COMMENT_NODE
736     10, 1, # DOCUMENT_TYPE_NODE
737     }->{$cn->node_type}) {
738     report Message::DOM::DOMException
739     -object => $self,
740     -type => 'HIERARCHY_REQUEST_ERR',
741     -subtype => 'CHILD_NODE_TYPE_ERR';
742     }
743     }
744 wakaba 1.1
745 wakaba 1.21 ## NOTE: Ancestor check here in |Node|.
746     }
747    
748     ## -- Insert at... ## NOTE: Only in insertBefore and replaceChild
749     my $index = -1; # last
750     if (defined $_[2]) {
751     ## error if $_[1] eq $_[2];
752    
753     my $cns = $self->child_nodes;
754     my $cnsl = @$cns;
755     C: {
756     $index = 0;
757     for my $i (0..($cnsl-1)) {
758     my $cn = $cns->[$i];
759     if ($cn eq $_[2]) {
760     $index += $i;
761     last C;
762     } elsif ($cn eq $_[1]) {
763     $index = -1; # offset
764     }
765     }
766 wakaba 1.1
767 wakaba 1.21 report Message::DOM::DOMException
768     -object => $self,
769     -type => 'NOT_FOUND_ERR',
770     -subtype => 'NOT_CHILD_ERR';
771     } # C
772     } else {
773     ## NOTE: Only in replaceChild
774     report Message::DOM::DOMException
775     -object => $self,
776     -type => 'NOT_FOUND_ERR',
777     -subtype => 'NOT_CHILD_ERR';
778     }
779 wakaba 1.1
780     ## -- Removes from parent
781 wakaba 1.21 if ($new_child_parent) {
782     if (@new_child == 1) {
783     my $v = $$new_child_parent->{child_nodes};
784 wakaba 1.1 RP: for my $i (0..$#$v) {
785 wakaba 1.13 if ($v->[$i] eq $new_child[0]) {
786 wakaba 1.1 splice @$v, $i, 1, ();
787     last RP;
788     }
789     } # RP
790 wakaba 1.21 } else {
791     @{$$new_child_parent->{child_nodes}} = ();
792 wakaba 1.1 }
793     }
794    
795     ## -- Rewrite the |parentNode| properties
796     for my $nc (@new_child) {
797 wakaba 1.21 $$nc->{parent_node} = $self;
798     Scalar::Util::weaken ($$nc->{parent_node});
799 wakaba 1.13 }
800 wakaba 1.1
801 wakaba 1.21 ## NOTE: Depends on method:
802     splice @{$$self->{child_nodes}}, $index, 1, @new_child;
803     delete ${$_[2]}->{parent_node};
804 wakaba 1.1
805 wakaba 1.21 ## NOTE: Only in |Document|.
806     for (@new_child) {
807     delete $$_->{implementation};
808     $$_->{owner_document} = $self;
809     Scalar::Util::weaken ($$_->{owner_document});
810     }
811    
812     return $_[2];
813     } # replace_child
814 wakaba 1.1
815 wakaba 1.21 ## |Document| attributes
816 wakaba 1.1
817 wakaba 1.21 ## NOTE: A manakai extension.
818     sub all_declarations_processed ($;$);
819 wakaba 1.1
820 wakaba 1.25 ## TODO: documentation
821     sub manakai_charset ($;$);
822    
823 wakaba 1.21 sub doctype ($) {
824     my $self = $_[0];
825     for (@{$self->child_nodes}) {
826     if ($_->node_type == 10) { # DOCUMENT_TYPE_NODE
827     return $_;
828     }
829     }
830     return undef;
831     } # doctype
832 wakaba 1.1
833 wakaba 1.21 sub document_element ($) {
834     my $self = shift;
835     for (@{$self->child_nodes}) {
836     if ($_->node_type == 1) { # ELEMENT_NODE
837     return $_;
838     }
839     }
840     return undef;
841     } # document_element
842 wakaba 1.1
843 wakaba 1.21 sub document_uri ($;$);
844 wakaba 1.1
845 wakaba 1.21 sub dom_config ($) {
846     require Message::DOM::DOMConfiguration;
847     return bless \\($_[0]), 'Message::DOM::DOMConfiguration';
848     } # dom_config
849 wakaba 1.1
850 wakaba 1.21 sub manakai_entity_base_uri ($;$) {
851     my $self = $_[0];
852     if (@_ > 1) {
853     if ($$self->{strict_error_checking}) {
854     if ($$self->{manakai_read_only}) {
855     report Message::DOM::DOMException
856     -object => $self,
857     -type => 'NO_MODIFICATION_ALLOWED_ERR',
858     -subtype => 'READ_ONLY_NODE_ERR';
859     }
860     }
861     if (defined $_[1]) {
862     $$self->{manakai_entity_base_uri} = ''.$_[1];
863     } else {
864     delete $$self->{manakai_entity_base_uri};
865     }
866     }
867 wakaba 1.1
868 wakaba 1.21 if (defined $$self->{manakai_entity_base_uri}) {
869     return $$self->{manakai_entity_base_uri};
870     } else {
871     return $$self->{document_uri};
872     }
873     } # manakai_entity_base_uri
874 wakaba 1.1
875 wakaba 1.25 ## TODO: documentation
876     sub manakai_has_bom ($;$);
877    
878 wakaba 1.21 sub input_encoding ($;$);
879 wakaba 1.1
880 wakaba 1.21 sub strict_error_checking ($;$) {
881     ## NOTE: Same as trivial boolean accessor, except no read-only checking.
882     if (@_ > 1) {
883     if ($_[1]) {
884     ${$_[0]}->{strict_error_checking} = 1;
885     } else {
886     delete ${$_[0]}->{strict_error_checking};
887     }
888     }
889     return ${$_[0]}->{strict_error_checking};
890     } # strict_error_checking
891 wakaba 1.1
892 wakaba 1.21 ## ISSUE: Setting manakai_is_html true shadows
893     ## xml_* properties. Is this desired?
894 wakaba 1.1
895 wakaba 1.21 sub xml_encoding ($;$) {
896     my $self = $_[0];
897     if (@_ > 1) {
898     ## NOTE: A manakai extension.
899     if ($$self->{strict_error_checking}) {
900     if ($$self->{manakai_is_html}) {
901     report Message::DOM::DOMException
902     -object => $self,
903     -type => 'NOT_SUPPORTED_ERR',
904     -subtype => 'NON_HTML_OPERATION_ERR';
905     }
906     if ($$self->{manakai_read_only}) {
907     report Message::DOM::DOMException
908     -object => $self,
909     -type => 'NO_MODIFICATION_ALLOWED_ERR',
910     -subtype => 'READ_ONLY_NODE_ERR';
911     }
912     }
913     if (defined $_[1]) {
914     $$self->{xml_encoding} = ''.$_[1];
915     } else {
916     delete $$self->{xml_encoding};
917     }
918     }
919    
920     if ($$self->{manakai_is_html}) {
921     return undef;
922     } else {
923     return $$self->{xml_encoding};
924     }
925     } # xml_encoding
926 wakaba 1.1
927 wakaba 1.21 sub xml_standalone ($;$) {
928     my $self = $_[0];
929     if (@_ > 1) {
930     if ($$self->{strict_error_checking}) {
931     if ($$self->{manakai_is_html}) {
932     report Message::DOM::DOMException
933     -object => $self,
934     -type => 'NOT_SUPPORTED_ERR',
935     -subtype => 'NON_HTML_OPERATION_ERR';
936     }
937     ## NOTE: Not in DOM3.
938     if ($$self->{manakai_read_only}) {
939     report Message::DOM::DOMException
940     -object => $self,
941     -type => 'NO_MODIFICATION_ALLOWED_ERR',
942     -subtype => 'READ_ONLY_NODE_ERR';
943     }
944     }
945     if ($_[1]) {
946     $$self->{xml_standalone} = 1;
947     } else {
948     delete $$self->{xml_standalone};
949     }
950     }
951    
952     if ($$self->{manakai_is_html}) {
953     return 0;
954     } else {
955     return $$self->{xml_standalone};
956     }
957     } # xml_standalone
958 wakaba 1.1
959 wakaba 1.21 sub xml_version ($;$) {
960     my $self = $_[0];
961     if (@_ > 1) {
962     my $v = ''.$_[1];
963     if ($$self->{strict_error_checking}) {
964     if ($$self->{manakai_is_html}) {
965     report Message::DOM::DOMException
966     -object => $self,
967     -type => 'NOT_SUPPORTED_ERR',
968     -subtype => 'NON_HTML_OPERATION_ERR';
969     }
970     if ($v ne '1.0' and $v ne '1.1') {
971     report Message::DOM::DOMException
972     -object => $self,
973     -type => 'NOT_SUPPORTED_ERR',
974     -subtype => 'UNKNOWN_XML_VERSION_ERR';
975     }
976     if ($$self->{manakai_read_only}) {
977     ## ISSUE: Not in DOM3.
978     report Message::DOM::DOMException
979     -object => $self,
980     -type => 'NO_MODIFICATION_ALLOWED_ERR',
981     -subtype => 'READ_ONLY_NODE_ERR';
982     }
983     }
984     $$self->{xml_version} = $v;
985     }
986    
987     if (defined wantarray) {
988     if ($$self->{manakai_is_html}) {
989     return undef;
990     } elsif (defined $$self->{xml_version}) {
991     return $$self->{xml_version};
992     } else {
993     return '1.0';
994     }
995     }
996     } # xml_version
997 wakaba 1.1
998 wakaba 1.21 ## |Document| methods
999 wakaba 1.1
1000 wakaba 1.21 sub get_element_by_id ($$) {
1001     local $Error::Depth = $Error::Depth + 1;
1002     my @nodes = @{$_[0]->child_nodes};
1003     N: while (@nodes) {
1004     my $node = shift @nodes;
1005     next N unless $node->node_type == 1; # ELEMENT_NODE
1006     for my $attr (@{$node->attributes}) {
1007     if ($attr->is_id and $attr->value eq $_[1]) {
1008     return $node;
1009     }
1010     }
1011     unshift @nodes, @{$node->child_nodes};
1012     } # N
1013     return undef;
1014     } # get_element_by_id
1015 wakaba 1.1
1016 wakaba 1.21 ## TODO: HTML5 case normalization
1017     sub get_elements_by_tag_name ($$) {
1018     my $name = ''.$_[1];
1019     my $chk;
1020     if ($name eq '*') {
1021     $chk = sub () { 1 };
1022     } else {
1023     $chk = sub ($) {
1024     return $_[0]->manakai_tag_name eq $name;
1025     };
1026     }
1027 wakaba 1.1
1028 wakaba 1.21 require Message::DOM::NodeList;
1029     return bless \[$_[0], $chk], 'Message::DOM::NodeList::GetElementsList';
1030     } # get_elements_by_tag_name
1031 wakaba 1.1
1032 wakaba 1.21 sub get_elements_by_tag_name_ns ($$$) {
1033     my $nsuri = defined $_[1] ? ''.$_[1] : '';
1034     my $lname = ''.$_[2];
1035     my $chk;
1036     if ($nsuri eq '*') {
1037     if ($lname eq '*') {
1038     $chk = sub () { 1 };
1039     } else {
1040     $chk = sub ($) {
1041     return $_[0]->manakai_local_name eq $lname;
1042     };
1043     }
1044     } elsif ($nsuri eq '') {
1045     if ($lname eq '*') {
1046     $chk = sub ($) {
1047     return not defined $_[0]->namespace_uri;
1048     };
1049     } else {
1050     $chk = sub ($) {
1051     return (not defined $_[0]->namespace_uri and
1052     $_[0]->manakai_local_name eq $lname);
1053     };
1054     }
1055     } else {
1056     if ($lname eq '*') {
1057     $chk = sub ($) {
1058     my $ns = $_[0]->namespace_uri;
1059     return (defined $ns and $ns eq $nsuri);
1060     };
1061     } else {
1062     $chk = sub ($) {
1063     my $ns = $_[0]->namespace_uri;
1064     return (defined $ns and $ns eq $nsuri and
1065     $_[0]->manakai_local_name eq $lname);
1066     };
1067     }
1068     }
1069 wakaba 1.1
1070 wakaba 1.21 require Message::DOM::NodeList;
1071     return bless \[$_[0], $chk], 'Message::DOM::NodeList::GetElementsList';
1072     } # get_elements_by_tag_name
1073 wakaba 1.1
1074 wakaba 1.21 ## TODO: import_node
1075 wakaba 1.1
1076 wakaba 1.21 ## TODO: normalize_document
1077 wakaba 1.1
1078 wakaba 1.21 ## TODO: rename_node
1079 wakaba 1.1
1080 wakaba 1.21 ## |DocumentTraversal| methods
1081 wakaba 1.1
1082 wakaba 1.21 ## TODO: create_node_iterator
1083 wakaba 1.1
1084 wakaba 1.21 sub manakai_create_serial_walker ($$;$$$);
1085 wakaba 1.1
1086 wakaba 1.21 sub create_tree_walker ($$;$$$);
1087 wakaba 1.1
1088 wakaba 1.28 ## |DocumentView| attribute
1089    
1090     sub default_view ($);
1091    
1092 wakaba 1.21 ## |HTMLDocument| attributes
1093 wakaba 1.1
1094 wakaba 1.21 sub compat_mode ($) {
1095     if (${$_[0]}->{manakai_is_html}) {
1096     if (defined ${$_[0]}->{manakai_compat_mode} and
1097     ${$_[0]}->{manakai_compat_mode} eq 'quirks') {
1098     return 'BackCompat';
1099     }
1100     }
1101     return 'CSS1Compat';
1102     } # compat_mode
1103 wakaba 1.1
1104 wakaba 1.21 sub manakai_compat_mode ($;$) {
1105     if (${$_[0]}->{manakai_is_html}) {
1106     if (@_ > 1 and defined $_[1] and
1107     {'no quirks' => 1, 'limited quirks' => 1, 'quirks' => 1}->{$_[1]}) {
1108     ${$_[0]}->{manakai_compat_mode} = $_[1];
1109     }
1110     return ${$_[0]}->{manakai_compat_mode} || 'no quirks';
1111 wakaba 1.1 } else {
1112 wakaba 1.21 return 'no quirks';
1113 wakaba 1.1 }
1114 wakaba 1.21 } # manakai_compat_mode
1115 wakaba 1.1
1116 wakaba 1.21 sub inner_html ($;$) {
1117     my $self = $_[0];
1118     local $Error::Depth = $Error::Depth + 1;
1119    
1120     if ($$self->{manakai_is_html}) {
1121     require Whatpm::HTML;
1122     if (@_ > 1) {
1123     ## Step 1
1124     ## TODO: Stop parsing and ...
1125    
1126     ## Step 2
1127     my @cn = @{$self->child_nodes};
1128     for (@cn) { ## NOTE: Might throw a |NO_MODIFICATION_ALLOWED_ERR|.
1129     $self->remove_child ($_); #
1130     }
1131 wakaba 1.1
1132 wakaba 1.21 ## Step 3, 4, 5
1133     Whatpm::HTML->parse_string ($_[1] => $self);
1134 wakaba 1.1
1135 wakaba 1.21 ## TODO:
1136     ## <script>var input = function_to_do_xmlhttprequest (location.href);
1137     ## document.innerHTML = input</script>
1138 wakaba 1.1
1139 wakaba 1.21 return unless defined wantarray;
1140     }
1141 wakaba 1.1
1142 wakaba 1.24 require Whatpm::HTML::Serializer;
1143     return ${ Whatpm::HTML::Serializer->get_inner_html ($self) };
1144 wakaba 1.21 } else {
1145     if (@_ > 1) {
1146     ## Step 1
1147     require Whatpm::XMLParser; # MUST
1148     my $doc = $self->implementation->create_document;
1149    
1150     ## Step 2
1151     #
1152 wakaba 1.1
1153 wakaba 1.21 ## Step 3
1154     $doc = Whatpm::XMLParser->parse_string ($_[1] => $doc); # MUST
1155 wakaba 1.1
1156 wakaba 1.21 ## Step 4
1157     #
1158 wakaba 1.1
1159 wakaba 1.21 ## Step 5
1160     ## TODO: ill-formed -> SYNTAX_ERR # MUST
1161 wakaba 1.1
1162 wakaba 1.21 ## Step 6 # MUST
1163     my @cn = @{$self->child_nodes}; ## TODO: If read-only
1164     for (@cn) {
1165     $self->remove_child ($_);
1166     }
1167 wakaba 1.1
1168 wakaba 1.21 ## Step 7, 8, 9, 10
1169     for my $node (@{$doc->child_nodes}) {
1170     $self->append_child ($self->adopt_node ($node));
1171     }
1172 wakaba 1.1
1173 wakaba 1.21 return unless defined wantarray;
1174     }
1175 wakaba 1.1
1176 wakaba 1.21 ## TODO: This serializer is currently not conformant to HTML5 spec.
1177     require Whatpm::XMLSerializer;
1178     my $r = '';
1179     for (@{$self->child_nodes}) {
1180     $r .= ${ Whatpm::XMLSerializer->get_outer_xml ($_, sub {
1181     ## TODO: INVALID_STATE_ERR
1182     }) };
1183     }
1184     return $r;
1185     }
1186     } # inner_html
1187 wakaba 1.1
1188 wakaba 1.21 sub manakai_is_html ($;$) {
1189     if (@_ > 1) {
1190     if ($_[1]) {
1191     ${$_[0]}->{manakai_is_html} = 1;
1192     } else {
1193     delete ${$_[0]}->{manakai_is_html};
1194     delete ${$_[0]}->{manakai_compat_mode};
1195     }
1196     }
1197     return ${$_[0]}->{manakai_is_html};
1198     } # manakai_is_html
1199 wakaba 1.1
1200 wakaba 1.21 package Message::IF::Document;
1201     package Message::IF::DocumentTraversal;
1202     package Message::IF::DocumentXDoctype;
1203 wakaba 1.22 package Message::IF::DocumentSelector;
1204 wakaba 1.21 package Message::IF::HTMLDocument;
1205 wakaba 1.1
1206 wakaba 1.21 package Message::DOM::DOMImplementation;
1207 wakaba 1.1
1208 wakaba 1.21 sub create_document ($;$$$) {
1209     my $r = Message::DOM::Document->____new ($_[0]);
1210 wakaba 1.1
1211 wakaba 1.21 if (defined $_[2]) {
1212     local $Error::Depth = $Error::Depth + 1;
1213     $r->append_child ($r->create_element_ns ($_[1], $_[2])); # NAMESPACE_ERR
1214     ## NOTE: manakai might raise DOMExceptions in cases not defined
1215     ## in DOM3Core spec: XMLNSPREFIX_NONXMLNSNS_ERR,
1216     ## XMLNS_NONXMLNSNS_ERR, and NONXMLNSPREFIX_XMLNSNS_ERR.
1217     } elsif (defined $_[1]) {
1218     report Message::DOM::DOMException
1219     -object => $_[0],
1220     -type => 'NAMESPACE_ERR',
1221     -subtype => 'QNAME_NULLNS_ERR';
1222     }
1223 wakaba 1.1
1224 wakaba 1.21 if (defined $_[3]) {
1225     if ($_[3]->parent_node) {
1226     report Message::DOM::DOMException
1227     -object => $_[0],
1228     -type => 'WRONG_DOCUMENT_ERR',
1229     -subtype => 'INUSE_DOCTYPE_ERR';
1230     }
1231     local $Error::Depth = $Error::Depth + 1;
1232     $r->insert_before ($_[3], $r->first_child); # EXTERNAL_OBJECT_ERR
1233     }
1234 wakaba 1.1
1235 wakaba 1.21 return $r;
1236     } # create_document
1237 wakaba 1.1
1238 wakaba 1.21 =head1 LICENSE
1239 wakaba 1.1
1240 wakaba 1.21 Copyright 2007 Wakaba <w@suika.fam.cx>
1241 wakaba 1.1
1242 wakaba 1.21 This program is free software; you can redistribute it and/or
1243     modify it under the same terms as Perl itself.
1244 wakaba 1.1
1245 wakaba 1.21 =cut
1246 wakaba 1.1
1247     1;
1248 wakaba 1.28 ## $Date: 2007/12/31 13:46:25 $

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24