/[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.30 - (hide annotations) (download)
Sat Apr 12 15:58:41 2008 UTC (16 years, 7 months ago) by wakaba
Branch: MAIN
Changes since 1.29: +4 -6 lines
++ manakai/lib/Message/DOM/ChangeLog	12 Apr 2008 14:24:10 -0000
2008-04-12  Wakaba  <wakaba@suika.fam.cx>

	* Element.pm (create_element, create_element_ns): Inputs
	were not normalized into a string.

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

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24